Understanding how to test spring beans.
Unit tests have many advantages. Testing facilitates:
-
validation of the component design in isolation, making it easier to debug when there’s a problem.
-
testing of functionality which is either not exposed or not easily accessible from the program’s external interfaces, for instance, error handling and functionality which has no UI.
-
a cheap way to ensure no major existing functionality is broken across the system when a cross-component change is made.
-
a means for people unfamiliar with the code to verify their changes haven’t broken anything. Additionally, tests provide an easy way to start understanding the functionality.
-
to automate what might otherwise be arduous manual testing.
We will cover testing with Spring as an embedded portion of every chapter. However, this chapter is focused on understanding the core testing framework Spring provides.
Spring tests use annotations, and are similar to JUnit tests.
Spring provides a JUnit test runner, @SpringRunner
or its legacy forerunner, @SpringJUnit4ClassRunner
.
Each Spring test can be launched with a JUnit runner hint on the test class:
@ExtendWith(SpringExtension.class)
Context for the test can be easily passed with an @ContextConfiguration
which looks for a
bean definition context file prefixed with the name of the class the test resides in.
ContextConfiguration can also supply an argument to list one or more java classes that are
annotated with a @Configuration
.
Spring testing relies heavily on the Liskov Substitution Principle. Thus, all Spring layers are typically coded as an interface plus its implementation. Testing with such an approach allows for replacing the implementation with a fake (mock) one that implements the higher interface.
This example demonstrates using a default XML context for testing code. This uses the name of
the test class with a suffix of -context.xml
under the resources.
-
The JUnit test
⇒ Ex01_DefaultXMLContextConfiguration.java
This class is a JUnit test marked with an annotation@ContextConfiguration
. This annotation hints at looking for an XML file with the same name (and under the same package), suffixed with-context.xml
. Thus running the class will cause Spring to search for a file namedEx01_DefaultXMLContextConfiguration-context.xml
on the classpath, and load beans from the XML file, should it be located. -
The XML file
⇒ Ex01_DefaultXMLContextConfiguration-context.xml
The default context configuration file (same package, name matches the Java class and adds a-context.xml
).
The @ContextConfiguration
without any arguments will look for an XML file in the same package
which has a name, with the convention <JavaClassName>-context.xml. Notice the package location of
this XML matches the package location of the Java class as well, even though it is not under
src/test/java, but under src/test/resources.
This XML is auto-loaded and beans defined in this XML are available for autowiring.
This example demonstrates using a custom XML context for testing code. This uses the name of the XML passed into as the location attribute.
-
The JUnit test
⇒ Ex02_CustomXMLContextConfiguration.java
This class is a JUnit test marked with an annotation@ContextConfiguration
. This annotation now includes alocations
attribute, specifying the XML file to load the context from. Thus running the class will cause Spring to search for the file on the classpath, and load beans from the XML file, should it be located. -
The XML file
⇒ ex02.xml
The XML file can have any name and any location.
The @ContextConfiguration
with the locations
attribute looks for the XML file in the classpath
specified. Notice that the XML file no longer needs a naming convention and that the location of
this XML is not connected to the Java class location, it just needs to be on the classpath.
This XML is auto-loaded and beans defined in this XML are available for autowiring.
This example demonstrates using a Java configuration context for testing code. There is no XML file,
the context is loaded from a Java class marked with the @Configuration
annotation.
-
The JUnit test
⇒ Ex03_JavaContextConfiguration.java
This class is a JUnit test marked with an annotation@ContextConfiguration
. This annotation now includes aclasses
attribute, specifying the class to load the context from. Thus running the class will cause Spring to search for the file on the classpath, and load beans from the XML file, should it be located. -
The Configuration class
⇒ DIConfiguration.java
This class is located under the main module and is scanned during the launch of the test code, and loads the beans defined in the class, into the context.
The @ContextConfiguration
with the classes
attribute looks for the Java configurations on the
classpath specified. Notice that the DIConfiguration
is stereotyped as a @Configuration
and it
also initiates a @ComponentScan
for the basePackage of the model. The scan, while not
necessary here, is shown as a means to load other components for the test, if and when necessary.
The configuration provides two different ColoredShapeHolder
instances, both of which can be
independently accessed in the test.
The lab exercise is to fix the broken tests. Follow the instructions to fix the TODOs to get the JUnit test to pass.
Prev | TOC | Next |
---|---|---|