Expert Spring MVC and Web Flow

(Dana P.) #1
This is why we must write integration tests, because there are neither any compiler checks
for the system’s configuration (short from simple DTD validity, non-semantic checks) nor unit
tests for exercising the configuration. The integration tests perform this crucial role for Spring
applications, and as you’ll see they are nearly as simple to create and run as unit tests.

Overview
The Spring Framework ships with a set of classes designed to enable effective and simple inte-
gration tests. Also found in spring-mock.jar, but unlike the Servlet API stubs, these classes are
specifically intended for Spring applications.
The intent of integration tests is to ensure the configuration of the components with the
Spring Framework is correct and functioning; therefore, it makes sense to begin the test with
a real ApplicationContext. In contrast, during unit tests we created every object and depend-
ency by hand, completely divorced from the container. During integration tests, all objects
and their dependencies will come from the ApplicationContext, just like they will during a
running application.
As you might imagine, if we are trying to keep all tests running extremely quickly, how to
we accomplish this while creating an ApplicationContextfor every test? To solve this problem,
the ApplicationContextis cached between test methods and loaded only once. This is a trade-
off to keep tests running quickly, especially when heavyweight objects exist such as
DataSourcesor connection pools.
The main base class for integration tests is org.springframework.test.
AbstractSpringContextTests. It is a subclass of JUnit’s TestCase, and it is responsible for
caching the ApplicationContextafter load and providing methods to reload the context if
required. However, its subclass, AbstractDependencyInjectionSpringContextTests, is what
most of your non-transactional tests will subclass. This class will use Dependency Injection to
populate the test class itself with required objects before the test methods are run. What better
way to retrieve dependencies for your test than through Dependency Injection itself!
Most integration tests will eventually run into the database, so tight control over transac-
tion demarcation is required inside integration tests. Normally we want to perform all of our
work under a transaction, but at the end of the test roll back the transaction to ensure that the
external world will be left in a clean state. Not only does this technique save us in the event we
have a test accidentally delete the entire database, but it allows future tests to run with
expected data available.
To help with database integration tests, Spring provides the handy
AbstractTransactionalSpringContextTests class, which is injected with an instance of a
PlatformTransactionManager during initialization. By default, this test class will begin a trans-
action before every test method and then roll it back during the teardown phase. If you do
wish to commit the transaction after your test run, you may call setComplete()before your
tests completes.
The main themes repeated in these classes are quickness and safety. Because integration
tests interact with the database, the potential for damage is much greater than with a simple
unit test. The classes provided by Spring allow for easy creation of tests that run quickly and
will, by default, clean up after every test method. If your tests do not require any database
interaction, then AbstractDependencyInjectionSpringContextTests is the class to choose. If
your tests do touch the database, we recommend AbstractTransactionalSpringContextTests
for simplified control over the transaction between and during test methods.

304 CHAPTER 10 ■TESTING SPRING MVC APPLICATIONS

Free download pdf