In this lab you will refactor the RewardNetworkTests
using Spring’s
system test support library to simplify and improve the performance
of your system. You will then use Spring profiles to define
multiple tests using different implementations of the AccountRepository
, RestaurantRepository
and RewardRepository
for different
environments.
What you will learn:
Specific subjects you will gain experience with:
Estimated time to complete: 30 minutes
Quick instructions for this exercise have been embedded within
the lab materials in the form of TODO comments. To display them,
open the Tasks
view (Window >> Show View >>
Tasks (not Task
List)). Use the view’s small down arrow to select
a Configure Contents…
menu, you’ll find the instructions are easy to follow if you
configure TODOs to display On any element in
the same project
.
Occasionally, TODO’S defined within XML files disappear
from the Tasks
view (i.e. gaps in the
number sequence). To correct this, go to Preferences >> General >> Editors
>> Structured Text Editor >> Task Tags
pane. Check Enable searching for Task
Tags
and click Clean and Redetect
Tasks
. On the Filters
tab,
ensure XML content type is checked.
In rewards.RewardNetworkTests
we
setup our test-environment using Spring in the @BeforeEach
setUp
method. Instead we are going to use
Spring’s test-extension. Comment out the @BeforeEach
method - highlight the method
and use CTRL+SHIFT+C
(on a Mac use
COMMAND+SHIFT+C
). Now run the test.
You will get a Red bar because the rewardNetwork
field is null.
Spring’s TestContext framework offers full support for
JUnit 5 via the SpringExtension
class.
Your next step is to tell JUnit to run your test using JUnit and then refactor your test as necessary to work with it. You will need to add 2 annotations just like the examples in the notes.
Tip | |
---|---|
In |
Now when you run your test the test runner’s setup logic
will use auto-wiring on your
test class to set values from the ApplicationContext. This means
your rewardNetwork
will be assigned to
the RewardNetwork bean from the context automatically.
Re-run your test in Eclipse and verify you get a green bar. If
so, the rewardNetwork
field is being
set properly for you. If you don’t see green, try to figure
out where the problem lies. If you can’t figure it out, ask
the instructor to help you find the issue.
Note | |
---|---|
When you have the green bar, you’ve successfully
reconfigured the rewards integration test, and at the same time
simplified your system test by leveraging Spring’s test
support. In addition, the performance of your system test has
potentially improved as the |
We can clear up what we no longer need by deleting the context
field and removing the @BeforeEach
and @AfterEach methods.
Rerun the test and check that "Clearing restaurant cache" appears on the console - this means the @PreDestroy method is still being invoked by Spring.
We are now going to modify the test to use different repository implementations - either Stubs or using JDBC.
First we are going to use the stub repositories in /src/test/java/rewards/internal
. We need to
make them Spring beans by annotating them as repository components.
Follow TODO 02
and annotate the stub
classes with @Repository
.
If you run RewardNetworkTests
again, it should fail because you have multiple beans of the same
type - the original JDBC implementations and now the stubs. To fix
this we will introduce two profiles: * The stub repositories will
belong to the "stub" profile * The JDBC repositories to the "jdbc"
profile.
Follow all the TODO 03
steps and
use the @Profile
annotation to put all
the repositories in this project into their correct profile - there
are 6 repository classes to annotate in total.
Finally annotate the RewardNetworkTests
class with
@ActiveProfiles to make "stub" the active profile. Rerun the test -
it should work now. Check the console to see that the stub
repository implementations are being used. Notice that the embedded
database is also being created even though we don’t use it.
We will fix this soon.
Switch the active-profile to "jdbc" instead (TODO 04
). Rerun the test - it should still
work. Check the console again to see that the JDBC repository
implementations are being used.
Profiles allow different configurations for different environments such as development, testing, QA (Quality Assurance), UAT (User Acceptance Testing), production and so forth. In the last step we will introduce two new profiles: "jdbc-dev" and "jdbc-production". In both cases we will be using the JDBC implementations of our repositories so two profiles will need to be active at once.
The difference between development and production is typically different infrastructure. In this case we are going to swap between an in-memory test database and the "real" database defined as a JNDI resource.
Modify TestInfrastructureDevConfig.java
so that all
the beans are members of the profile called "jdbc-dev" (TODO 05
).
Does RewardNetworkTests
still run
OK? Why not?
Fix the test by adding the "jdbc-dev" profile to the @ActiveProfiles
annotation in RewardNetworkTests
(TODO 06
). Remember you will need to retain
the "jdbc" profile as well. Rerun the test - it should work
again.
We have already setup the production dataSource for you using a
JNDI lookup (see TODO 07
). We have
used a standalone JNDI implementation - normally JNDI would be
provided by your JEE container (such as Tomcat or tc Server).
Change the active profile of RewardNetworkTests
from "jdbc-dev" to
"jdbc-production". Rerun the test, it should still work. To see
what has changed, look at the console and you will see logging from
an extra bean called SimpleJndiHelper
.
Switch the profile back to "jdbc-dev" and rerun. Check the console
and note that the SimpleJndiHelper
is
no longer used.
When no class or XML file is specified, Spring’s test
framework will look for an inner static class marked with
@Configuration (If none is found it will then look for an XML file
name of <Classname>-context.xml
). Since the
TestInfrastructureConfig
class is so
small anyway, copy the entire class definition, including
annotations, to an inner static class within the test class. Then
remove the configuration class reference from the @SpringJUnitConfig
annotation (no property
in the brackets).
This is an example of convention over configuration. Does the test still run?
Note | |
---|---|
When you copy the |