3768 lines
180 KiB
XML
3768 lines
180 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
||
<chapter version="5.0"
|
||
xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
|
||
xml:id="testing" xmlns="http://docbook.org/ns/docbook"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||
xmlns:xl="http://www.w3.org/1999/xlink"
|
||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||
xmlns:ns2="http://www.w3.org/1998/Math/MathML"
|
||
xmlns:ns="http://docbook.org/ns/docbook">
|
||
<title>Testing</title>
|
||
|
||
<section xml:id="testing-introduction">
|
||
<title>Introduction to Spring Testing</title>
|
||
|
||
<para>Testing is an integral part of enterprise software development. This
|
||
chapter focuses on the value-add of the IoC principle to <link
|
||
linkend="unit-testing">unit testing</link> and on the benefits of the Spring
|
||
Framework's support for <link linkend="integration-testing">integration
|
||
testing</link>. <emphasis>(A thorough treatment of testing in the enterprise
|
||
is beyond the scope of this reference manual.)</emphasis></para>
|
||
</section>
|
||
|
||
<section xml:id="unit-testing">
|
||
<title>Unit Testing</title>
|
||
|
||
<para>Dependency Injection should make your code less dependent on the
|
||
container than it would be with traditional Java EE development. The POJOs
|
||
that make up your application should be testable in JUnit or TestNG tests,
|
||
with objects simply instantiated using the <literal>new</literal> operator,
|
||
<emphasis>without Spring or any other container</emphasis>. You can use
|
||
<link linkend="mock-objects">mock objects</link> (in conjunction with other
|
||
valuable testing techniques) to test your code in isolation. If you follow
|
||
the architecture recommendations for Spring, the resulting clean layering
|
||
and componentization of your codebase will facilitate easier unit testing.
|
||
For example, you can test service layer objects by stubbing or mocking DAO
|
||
or Repository interfaces, without needing to access persistent data while
|
||
running unit tests.</para>
|
||
|
||
<para>True unit tests typically run extremely quickly, as there is no
|
||
runtime infrastructure to set up. Emphasizing true unit tests as part of
|
||
your development methodology will boost your productivity. You may not need
|
||
this section of the testing chapter to help you write effective unit tests
|
||
for your IoC-based applications. For certain unit testing scenarios,
|
||
however, the Spring Framework provides the following mock objects and
|
||
testing support classes.</para>
|
||
|
||
<section xml:id="mock-objects">
|
||
<title>Mock Objects</title>
|
||
|
||
<section xml:id="mock-objects-env">
|
||
<title>Environment</title>
|
||
|
||
<para>The <literal>org.springframework.mock.env</literal> package
|
||
contains mock implementations of the
|
||
<interfacename>Environment</interfacename> and
|
||
<interfacename>PropertySource</interfacename> abstractions introduced in
|
||
Spring 3.1 (see <xref linkend="new-in-3.1-environment-abstraction"/> and
|
||
<xref linkend="new-in-3.1-property-source-abstraction"/>).
|
||
<classname>MockEnvironment</classname> and
|
||
<classname>MockPropertySource</classname> are useful for developing
|
||
<emphasis>out-of-container</emphasis> tests for code that depends on
|
||
environment-specific properties.</para>
|
||
</section>
|
||
|
||
<section xml:id="mock-objects-jndi">
|
||
<title>JNDI</title>
|
||
|
||
<para>The <literal>org.springframework.mock.jndi</literal> package
|
||
contains an implementation of the JNDI SPI, which you can use to set up
|
||
a simple JNDI environment for test suites or stand-alone applications.
|
||
If, for example, JDBC <classname>DataSource</classname>s get bound to
|
||
the same JNDI names in test code as within a Java EE container, you can
|
||
reuse both application code and configuration in testing scenarios
|
||
without modification.</para>
|
||
</section>
|
||
|
||
<section xml:id="mock-objects-servlet">
|
||
<title>Servlet API</title>
|
||
|
||
<para>The <literal>org.springframework.mock.web</literal> package
|
||
contains a comprehensive set of Servlet API mock objects, targeted at
|
||
usage with Spring's Web MVC framework, which are useful for testing web
|
||
contexts and controllers. These mock objects are generally more
|
||
convenient to use than dynamic mock objects such as <link
|
||
xl:href="http://www.easymock.org">EasyMock</link> or existing Servlet
|
||
API mock objects such as <link
|
||
xl:href="http://www.mockobjects.com">MockObjects</link>.</para>
|
||
</section>
|
||
|
||
<section xml:id="mock-objects-portlet">
|
||
<title>Portlet API</title>
|
||
|
||
<para>The <literal>org.springframework.mock.web.portlet</literal>
|
||
package contains a set of Portlet API mock objects, targeted at usage
|
||
with Spring's Portlet MVC framework.</para>
|
||
</section>
|
||
</section>
|
||
|
||
<section xml:id="unit-testing-support-classes">
|
||
<title>Unit Testing support Classes</title>
|
||
|
||
<section xml:id="unit-testing-utilities">
|
||
<title>General utilities</title>
|
||
|
||
<para>The <literal>org.springframework.test.util</literal> package
|
||
contains <classname>ReflectionTestUtils</classname>, which is a
|
||
collection of reflection-based utility methods. Developers use these
|
||
methods in unit and integration testing scenarios in which they need to
|
||
set a non-<literal>public</literal> field or invoke a
|
||
non-<literal>public</literal> setter method when testing application
|
||
code involving, for example:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>ORM frameworks such as JPA and Hibernate that condone
|
||
<literal>private</literal> or <literal>protected</literal> field
|
||
access as opposed to <literal>public</literal> setter methods for
|
||
properties in a domain entity.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>Spring's support for annotations such as
|
||
<interfacename>@Autowired</interfacename>,
|
||
<interfacename>@Inject</interfacename>, and
|
||
<interfacename>@Resource,</interfacename> which provides dependency
|
||
injection for <literal>private</literal> or
|
||
<literal>protected</literal> fields, setter methods, and
|
||
configuration methods.</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</section>
|
||
|
||
<section xml:id="unit-testing-spring-mvc">
|
||
<title>Spring MVC</title>
|
||
|
||
<para>The <literal>org.springframework.test.web</literal> package
|
||
contains <classname>ModelAndViewAssert</classname>, which you can use in
|
||
combination with JUnit, TestNG, or any other testing framework for unit
|
||
tests dealing with Spring MVC <classname>ModelAndView</classname>
|
||
objects.</para>
|
||
|
||
<tip>
|
||
<title>Unit testing Spring MVC Controllers</title>
|
||
|
||
<para>To test your Spring MVC <literal>Controller</literal>s, use
|
||
<classname>ModelAndViewAssert</classname> combined with
|
||
<literal>MockHttpServletRequest</literal>,
|
||
<literal>MockHttpSession</literal>, and so on from the <link
|
||
linkend="mock-objects-servlet">
|
||
<literal>org.springframework.mock.web</literal></link> package.</para>
|
||
</tip>
|
||
</section>
|
||
</section>
|
||
</section>
|
||
|
||
<section xml:id="integration-testing">
|
||
<title>Integration Testing</title>
|
||
|
||
<section xml:id="integration-testing-overview">
|
||
<title>Overview</title>
|
||
|
||
<para>It is important to be able to perform some integration testing
|
||
without requiring deployment to your application server or connecting to
|
||
other enterprise infrastructure. This will enable you to test things such
|
||
as:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>The correct wiring of your Spring IoC container contexts.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>Data access using JDBC or an ORM tool. This would include such
|
||
things as the correctness of SQL statements, Hibernate queries, JPA
|
||
entity mappings, etc.</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<para>The Spring Framework provides first-class support for integration
|
||
testing in the <filename class="libraryfile">spring-test</filename>
|
||
module. The name of the actual JAR file might include the release version
|
||
and might also be in the long
|
||
<filename>org.springframework.test</filename> form, depending on where you
|
||
get it from (see the <link linkend="dependency-management">section on
|
||
Dependency Management</link> for an explanation). This library includes
|
||
the <literal>org.springframework.test</literal> package, which contains
|
||
valuable classes for integration testing with a Spring container. This
|
||
testing does not rely on an application server or other deployment
|
||
environment. Such tests are slower to run than unit tests but much faster
|
||
than the equivalent Cactus tests or remote tests that rely on deployment
|
||
to an application server.</para>
|
||
|
||
<para>In Spring 2.5 and later, unit and integration testing support is
|
||
provided in the form of the annotation-driven <link
|
||
linkend="testcontext-framework">Spring TestContext Framework</link>. The
|
||
TestContext framework is agnostic of the actual testing framework in use,
|
||
thus allowing instrumentation of tests in various environments including
|
||
JUnit, TestNG, and so on.</para>
|
||
|
||
<warning>
|
||
<title>JUnit 3.8 support is deprecated</title>
|
||
|
||
<para>As of Spring 3.0, the legacy JUnit 3.8 base class hierarchy (i.e.,
|
||
<classname>AbstractDependencyInjectionSpringContextTests</classname>,
|
||
<classname>AbstractTransactionalDataSourceSpringContextTests</classname>,
|
||
etc.) is officially deprecated and will be removed in a later release.
|
||
Any test classes based on this code should be migrated to the <link
|
||
linkend="testcontext-framework">Spring TestContext
|
||
Framework</link>.</para>
|
||
|
||
<para>As of Spring 3.1, the JUnit 3.8 base classes in the Spring
|
||
TestContext Framework (i.e.,
|
||
<classname>AbstractJUnit38SpringContextTests</classname> and
|
||
<classname>AbstractTransactionalJUnit38SpringContextTests</classname>)
|
||
and <interfacename>@ExpectedException</interfacename> have been
|
||
officially deprecated and will be removed in a later release. Any test
|
||
classes based on this code should be migrated to the JUnit 4 or TestNG
|
||
support provided by the <link linkend="testcontext-framework">Spring
|
||
TestContext Framework</link>. Similarly, any test methods annotated with
|
||
<interfacename>@ExpectedException</interfacename> should be modified to
|
||
use the built-in support for expected exceptions in JUnit and
|
||
TestNG.</para>
|
||
</warning>
|
||
</section>
|
||
|
||
<section xml:id="integration-testing-goals">
|
||
<title>Goals of Integration Testing</title>
|
||
|
||
<para>Spring's integration testing support has the following primary
|
||
goals:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>To manage <link linkend="testing-ctx-management">Spring IoC
|
||
container caching</link> between test execution.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>To provide <link linkend="testing-fixture-di">Dependency
|
||
Injection of test fixture instances</link>.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>To provide <link linkend="testing-tx">transaction
|
||
management</link> appropriate to integration testing.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>To supply <link
|
||
linkend="testing-support-classes">Spring-specific base classes</link>
|
||
that assist developers in writing integration tests.</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<para>The next few sections describe each goal and provide links to
|
||
implementation and configuration details.</para>
|
||
|
||
<section xml:id="testing-ctx-management">
|
||
<title>Context management and caching</title>
|
||
|
||
<para>The Spring TestContext Framework provides consistent loading of
|
||
Spring <classname>ApplicationContext</classname>s and
|
||
<classname>WebApplicationContext</classname>s as well as caching of
|
||
those contexts. Support for the caching of loaded contexts is important,
|
||
because startup time can become an issue — not because of the overhead
|
||
of Spring itself, but because the objects instantiated by the Spring
|
||
container take time to instantiate. For example, a project with 50 to
|
||
100 Hibernate mapping files might take 10 to 20 seconds to load the
|
||
mapping files, and incurring that cost before running every test in
|
||
every test fixture leads to slower overall test runs that reduce
|
||
developer productivity.</para>
|
||
|
||
<para>Test classes typically declare either an array of
|
||
<emphasis>resource locations</emphasis> for XML configuration metadata —
|
||
often in the classpath — or an array of <emphasis>annotated
|
||
classes</emphasis> that is used to configure the application. These
|
||
locations or classes are the same as or similar to those specified in
|
||
<literal>web.xml</literal> or other deployment configuration
|
||
files.</para>
|
||
|
||
<para>By default, once loaded, the configured
|
||
<interfacename>ApplicationContext</interfacename> is reused for each
|
||
test. Thus the setup cost is incurred only once per test suite, and
|
||
subsequent test execution is much faster. In this context, the term
|
||
<emphasis>test suite</emphasis> means all tests run in the same JVM —
|
||
for example, all tests run from an Ant, Maven, or Gradle build for a
|
||
given project or module. In the unlikely case that a test corrupts the
|
||
application context and requires reloading — for example, by modifying a
|
||
bean definition or the state of an application object — the TestContext
|
||
framework can be configured to reload the configuration and rebuild the
|
||
application context before executing the next test.</para>
|
||
|
||
<para>See <xref linkend="testcontext-ctx-management"/> and <xref
|
||
linkend="testcontext-ctx-management-caching"/> with the TestContext
|
||
framework.</para>
|
||
</section>
|
||
|
||
<section xml:id="testing-fixture-di">
|
||
<title>Dependency Injection of test fixtures</title>
|
||
|
||
<para>When the TestContext framework loads your application context, it
|
||
can optionally configure instances of your test classes via Dependency
|
||
Injection. This provides a convenient mechanism for setting up test
|
||
fixtures using preconfigured beans from your application context. A
|
||
strong benefit here is that you can reuse application contexts across
|
||
various testing scenarios (e.g., for configuring Spring-managed object
|
||
graphs, transactional proxies, <classname>DataSource</classname>s,
|
||
etc.), thus avoiding the need to duplicate complex test fixture setup
|
||
for individual test cases.</para>
|
||
|
||
<para>As an example, consider the scenario where we have a class,
|
||
<classname>HibernateTitleRepository</classname>, that implements data
|
||
access logic for a <classname>Title</classname> domain entity. We want
|
||
to write integration tests that test the following areas:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>The Spring configuration: basically, is everything related to
|
||
the configuration of the
|
||
<classname>HibernateTitleRepository</classname> bean correct and
|
||
present?</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>The Hibernate mapping file configuration: is everything mapped
|
||
correctly, and are the correct lazy-loading settings in
|
||
place?</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>The logic of the
|
||
<classname>HibernateTitleRepository</classname>: does the configured
|
||
instance of this class perform as anticipated?</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<para>See dependency injection of test fixtures with the <link
|
||
linkend="testcontext-fixture-di">TestContext framework</link>.</para>
|
||
</section>
|
||
|
||
<section xml:id="testing-tx">
|
||
<title>Transaction management</title>
|
||
|
||
<para>One common issue in tests that access a real database is their
|
||
effect on the state of the persistence store. Even when you're using a
|
||
development database, changes to the state may affect future tests.
|
||
Also, many operations — such as inserting or modifying persistent data —
|
||
cannot be performed (or verified) outside a transaction.</para>
|
||
|
||
<para>The TestContext framework addresses this issue. By default, the
|
||
framework will create and roll back a transaction for each test. You
|
||
simply write code that can assume the existence of a transaction. If you
|
||
call transactionally proxied objects in your tests, they will behave
|
||
correctly, according to their configured transactional semantics. In
|
||
addition, if a test method deletes the contents of selected tables while
|
||
running within the transaction managed for the test, the transaction
|
||
will roll back by default, and the database will return to its state
|
||
prior to execution of the test. Transactional support is provided to a
|
||
test via a <classname>PlatformTransactionManager</classname> bean
|
||
defined in the test's application context.</para>
|
||
|
||
<para>If you want a transaction to commit — unusual, but occasionally
|
||
useful when you want a particular test to populate or modify the
|
||
database — the TestContext framework can be instructed to cause the
|
||
transaction to commit instead of roll back via the <link
|
||
linkend="integration-testing-annotations"><interfacename>@TransactionConfiguration</interfacename></link>
|
||
and <link
|
||
linkend="integration-testing-annotations"><interfacename>@Rollback</interfacename></link>
|
||
annotations.</para>
|
||
|
||
<para>See transaction management with the <link
|
||
linkend="testcontext-tx">TestContext framework</link>.</para>
|
||
</section>
|
||
|
||
<section xml:id="testing-support-classes">
|
||
<title>Support classes for integration testing</title>
|
||
|
||
<para>The Spring TestContext Framework provides several
|
||
<literal>abstract</literal> support classes that simplify the writing of
|
||
integration tests. These base test classes provide well-defined hooks
|
||
into the testing framework as well as convenient instance variables and
|
||
methods, which enable you to access:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>The <literal>ApplicationContext</literal>, for performing
|
||
explicit bean lookups or testing the state of the context as a
|
||
whole.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>A <classname>JdbcTemplate</classname>, for executing SQL
|
||
statements to query the database. Such queries can be used to
|
||
confirm database state both <emphasis>prior to</emphasis> and
|
||
<emphasis>after</emphasis> execution of database-related application
|
||
code, and Spring ensures that such queries run in the scope of the
|
||
same transaction as the application code. When used in conjunction
|
||
with an ORM tool, be sure to avoid <link
|
||
linkend="testcontext-tx-false-positives">false
|
||
positives</link>.</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<para>In addition, you may want to create your own custom,
|
||
application-wide superclass with instance variables and methods specific
|
||
to your project.</para>
|
||
|
||
<para>See support classes for the <link
|
||
linkend="testcontext-support-classes">TestContext
|
||
framework</link>.</para>
|
||
</section>
|
||
</section>
|
||
|
||
<section xml:id="integration-testing-support-jdbc">
|
||
<title>JDBC Testing Support</title>
|
||
|
||
<para>The <literal>org.springframework.test.jdbc</literal> package
|
||
contains <classname>JdbcTestUtils</classname>, which is a collection of
|
||
JDBC related utility functions intended to simplify standard database
|
||
testing scenarios. <emphasis>Note that <link
|
||
linkend="testcontext-support-classes-junit4"><classname>AbstractTransactionalJUnit4SpringContextTests</classname></link>
|
||
and <link
|
||
linkend="testcontext-support-classes-testng"><classname>AbstractTransactionalTestNGSpringContextTests</classname></link>
|
||
provide convenience methods which delegate to
|
||
<classname>JdbcTestUtils</classname> internally.</emphasis></para>
|
||
|
||
<para>The <literal>spring-jdbc</literal> module provides support for
|
||
configuring and launching an embedded database which can be used in
|
||
integration tests that interact with a database. For details, see <xref
|
||
linkend="jdbc-embedded-database-support"/> and <xref
|
||
linkend="jdbc-embedded-database-dao-testing"/>.</para>
|
||
</section>
|
||
|
||
<section xml:id="integration-testing-annotations">
|
||
<title>Annotations</title>
|
||
|
||
<section xml:id="integration-testing-annotations-spring">
|
||
<title>Spring Testing Annotations</title>
|
||
|
||
<para>The Spring Framework provides the following set of
|
||
<emphasis>Spring-specific</emphasis> annotations that you can use in
|
||
your unit and integration tests in conjunction with the TestContext
|
||
framework. Refer to the respective Javadoc for further information,
|
||
including default attribute values, attribute aliases, and so on.</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@ContextConfiguration</interfacename>
|
||
</emphasis></para>
|
||
|
||
<para>Defines class-level metadata that is used to determine how to
|
||
load and configure an
|
||
<interfacename>ApplicationContext</interfacename> for integration
|
||
tests. Specifically,
|
||
<interfacename>@ContextConfiguration</interfacename> declares
|
||
<emphasis>either</emphasis> the application context resource
|
||
<varname>locations</varname> <emphasis>or</emphasis> the annotated
|
||
<varname>classes</varname> that will be used to load the
|
||
context.</para>
|
||
|
||
<para>Resource locations are typically XML configuration files
|
||
located in the classpath; whereas, annotated classes are typically
|
||
<interfacename>@Configuration</interfacename> classes. However,
|
||
resource locations can also refer to files in the file system, and
|
||
annotated classes can be component classes, etc.</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@ContextConfiguration</emphasis>("/test-config.xml")
|
||
public class XmlApplicationContextTests {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@ContextConfiguration</emphasis>(<emphasis
|
||
role="bold">classes</emphasis> = TestConfig.class)
|
||
public class ConfigClassApplicationContextTests {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para>As an alternative or in addition to declaring resource
|
||
locations or annotated classes,
|
||
<interfacename>@ContextConfiguration</interfacename> may be used to
|
||
declare <interfacename>ApplicationContextInitializer</interfacename>
|
||
classes.</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@ContextConfiguration</emphasis>(<emphasis
|
||
role="bold">initializers</emphasis> = CustomContextIntializer.class)
|
||
public class ContextInitializerTests {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para><interfacename>@ContextConfiguration</interfacename> may
|
||
optionally be used to declare the
|
||
<interfacename>ContextLoader</interfacename> strategy as well. Note,
|
||
however, that you typically do not need to explicitly configure the
|
||
loader since the default loader supports either resource
|
||
<varname>locations</varname> or annotated <varname>classes</varname>
|
||
as well as <varname>initializers</varname>.</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@ContextConfiguration</emphasis>(<emphasis
|
||
role="bold">locations</emphasis> = "/test-context.xml", <emphasis
|
||
role="bold">loader</emphasis> = CustomContextLoader.class)
|
||
public class CustomLoaderXmlApplicationContextTests {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<note>
|
||
<para><interfacename>@ContextConfiguration</interfacename>
|
||
provides support for <emphasis>inheriting</emphasis> resource
|
||
locations or configuration classes as well as context initializers
|
||
declared by superclasses by default.</para>
|
||
</note>
|
||
|
||
<para>See <xref linkend="testcontext-ctx-management"/> and the
|
||
Javadoc for <interfacename>@ContextConfiguration</interfacename> for
|
||
further details.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis
|
||
role="bold"><interfacename>@WebAppConfiguration</interfacename></emphasis></para>
|
||
|
||
<para>A class-level annotation that is used to declare that the
|
||
<interfacename>ApplicationContext</interfacename> loaded for an
|
||
integration test should be a
|
||
<interfacename>WebApplicationContext</interfacename>. The mere
|
||
presence of <interfacename>@WebAppConfiguration</interfacename> on a
|
||
test class ensures that a
|
||
<interfacename>WebApplicationContext</interfacename> will be loaded
|
||
for the test, using the default value of
|
||
<literal>"file:src/main/webapp"</literal> for the path to the root
|
||
of the web application (i.e., the <emphasis>resource base
|
||
path</emphasis>). The resource base path is used behind the scenes
|
||
to create a <classname>MockServletContext</classname> which serves
|
||
as the <interfacename>ServletContext</interfacename> for the test's
|
||
<interfacename>WebApplicationContext</interfacename>.</para>
|
||
|
||
<programlisting language="java">@ContextConfiguration
|
||
<emphasis role="bold">@WebAppConfiguration</emphasis>
|
||
public class WebAppTests {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para>To override the default, specify a different base resource
|
||
path via the <emphasis>implicit</emphasis>
|
||
<interfacename>value</interfacename> attribute. Both
|
||
<literal>classpath:</literal> and <literal>file:</literal> resource
|
||
prefixes are supported. If no resource prefix is supplied the path
|
||
is assumed to be a file system resource.</para>
|
||
|
||
<programlisting language="java">@ContextConfiguration
|
||
<emphasis role="bold">@WebAppConfiguration("classpath:test-web-resources")</emphasis>
|
||
public class WebAppTests {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para>Note that <interfacename>@WebAppConfiguration</interfacename>
|
||
must be used in conjunction with
|
||
<interfacename>@ContextConfiguration</interfacename>, either within
|
||
a single test class or within a test class hierarchy. See the
|
||
Javadoc for <interfacename>@WebAppConfiguration</interfacename> for
|
||
further details.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@ContextHierarchy</interfacename></emphasis></para>
|
||
|
||
<para>A class-level annotation that is used to define a hierarchy of
|
||
<interfacename>ApplicationContext</interfacename>s for integration
|
||
tests. <interfacename>@ContextHierarchy</interfacename> should be
|
||
declared with a list of one or more
|
||
<interfacename>@ContextConfiguration</interfacename> instances, each
|
||
of which defines a level in the context hierarchy. The following
|
||
examples demonstrate the use of
|
||
<interfacename>@ContextHierarchy</interfacename> within a single
|
||
test class; however,
|
||
<interfacename>@ContextHierarchy</interfacename> can also be used
|
||
within a test class hierarchy.</para>
|
||
|
||
<programlisting language="java">@ContextHierarchy({
|
||
@ContextConfiguration("/parent-config.xml"),
|
||
@ContextConfiguration("/child-config.xml")
|
||
})
|
||
public class ContextHierarchyTests {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<programlisting language="java">@WebAppConfiguration
|
||
@ContextHierarchy({
|
||
@ContextConfiguration(classes = AppConfig.class),
|
||
@ContextConfiguration(classes = WebConfig.class)
|
||
})
|
||
public class WebIntegrationTests {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para>If you need to merge or override the configuration for a given
|
||
level of the context hierarchy within a test class hierarchy, you
|
||
must explicitly name that level by supplying the same value to the
|
||
<varname>name</varname> attribute in
|
||
<interfacename>@ContextConfiguration</interfacename> at each
|
||
corresponding level in the class hierarchy. See <xref
|
||
linkend="testcontext-ctx-management-ctx-hierarchies"/> and the
|
||
Javadoc for <interfacename>@ContextHierarchy</interfacename> for
|
||
further examples.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@ActiveProfiles</interfacename> </emphasis></para>
|
||
|
||
<para>A class-level annotation that is used to declare which
|
||
<emphasis>bean definition profiles</emphasis> should be active when
|
||
loading an <interfacename>ApplicationContext</interfacename> for
|
||
test classes.</para>
|
||
|
||
<programlisting language="java">@ContextConfiguration
|
||
<emphasis role="bold">@ActiveProfiles</emphasis>("dev")
|
||
public class DeveloperTests {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<programlisting language="java">@ContextConfiguration
|
||
<emphasis role="bold">@ActiveProfiles</emphasis>({"dev", "integration"})
|
||
public class DeveloperIntegrationTests {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<note>
|
||
<para><interfacename>@ActiveProfiles</interfacename> provides
|
||
support for <emphasis>inheriting</emphasis> active bean definition
|
||
profiles declared by superclasses by default.</para>
|
||
</note>
|
||
|
||
<para>See <xref linkend="testcontext-ctx-management-env-profiles"/>
|
||
and the Javadoc for <interfacename>@ActiveProfiles</interfacename>
|
||
for examples and further details.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@DirtiesContext</interfacename> </emphasis></para>
|
||
|
||
<para>Indicates that the underlying Spring
|
||
<interfacename>ApplicationContext</interfacename> has been
|
||
<emphasis>dirtied</emphasis> during the execution of a test (i.e.,
|
||
modified or corrupted in some manner — for example, by changing the
|
||
state of a singleton bean) and should be closed, regardless of
|
||
whether the test passed. When an application context is marked
|
||
<emphasis>dirty</emphasis>, it is removed from the testing
|
||
framework's cache and closed. As a consequence, the underlying
|
||
Spring container will be rebuilt for any subsequent test that
|
||
requires a context with the same configuration metadata.</para>
|
||
|
||
<para><interfacename>@DirtiesContext</interfacename> can be used as
|
||
both a class-level and method-level annotation within the same test
|
||
class. In such scenarios, the
|
||
<interfacename>ApplicationContext</interfacename> is marked as
|
||
<emphasis>dirty</emphasis> after any such annotated method as well
|
||
as after the entire class. If the <classname>ClassMode</classname>
|
||
is set to <literal>AFTER_EACH_TEST_METHOD</literal>, the context is
|
||
marked dirty after each test method in the class.</para>
|
||
|
||
<para>The following examples explain when the context would be
|
||
dirtied for various configuration scenarios:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>After the current test class, when declared on a class
|
||
with class mode set to <literal>AFTER_CLASS</literal> (i.e., the
|
||
default class mode).</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@DirtiesContext</emphasis>
|
||
public class ContextDirtyingTests {
|
||
<lineannotation>// some tests that result in the Spring container being dirtied</lineannotation>
|
||
}</programlisting>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>After each test method in the current test class, when
|
||
declared on a class with class mode set to
|
||
<literal>AFTER_EACH_TEST_METHOD.</literal><programlisting
|
||
language="java"><emphasis role="bold">@DirtiesContext</emphasis>(<emphasis
|
||
role="bold">classMode</emphasis> = ClassMode.AFTER_EACH_TEST_METHOD)
|
||
public class ContextDirtyingTests {
|
||
<lineannotation>// some tests that result in the Spring container being dirtied</lineannotation>
|
||
}</programlisting></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>After the current test, when declared on a method.</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@DirtiesContext</emphasis>
|
||
@Test
|
||
public void testProcessWhichDirtiesAppCtx() {
|
||
<lineannotation>// some logic that results in the Spring container being dirtied</lineannotation>
|
||
}</programlisting>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<para>If <interfacename>@DirtiesContext</interfacename> is used in a
|
||
test whose context is configured as part of a context hierarchy via
|
||
<interfacename>@ContextHierarchy</interfacename>, the
|
||
<varname>hierarchyMode</varname> flag can be used to control how the
|
||
context cache is cleared. By default an
|
||
<emphasis>exhaustive</emphasis> algorithm will be used that clears
|
||
the context cache including not only the current level but also all
|
||
other context hierarchies that share an ancestor context common to
|
||
the current test; all
|
||
<interfacename>ApplicationContext</interfacename>s that reside in a
|
||
sub-hierarchy of the common ancestor context will be removed from
|
||
the context cache and closed. If the <emphasis>exhaustive</emphasis>
|
||
algorithm is overkill for a particular use case, the simpler
|
||
<emphasis>current level</emphasis> algorithm can be specified
|
||
instead, as seen below.</para>
|
||
|
||
<programlisting language="java">@ContextHierarchy({
|
||
@ContextConfiguration("/parent-config.xml"),
|
||
@ContextConfiguration("/child-config.xml")
|
||
})
|
||
public class BaseTests {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}
|
||
|
||
public class ExtendedTests extends BaseTests {
|
||
|
||
@Test
|
||
@DirtiesContext(<emphasis role="bold">hierarchyMode = HierarchyMode.CURRENT_LEVEL</emphasis>)
|
||
public void test() {
|
||
<lineannotation>// some logic that results in the child context being dirtied</lineannotation>
|
||
}
|
||
}</programlisting>
|
||
|
||
<para>For further details regarding the
|
||
<constant>EXHAUSTIVE</constant> and
|
||
<constant>CURRENT_LEVEL</constant> algorithms see the Javadoc for
|
||
<interfacename>DirtiesContext.HierarchyMode</interfacename>.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@TestExecutionListeners</interfacename>
|
||
</emphasis></para>
|
||
|
||
<para>Defines class-level metadata for configuring which
|
||
<interfacename>TestExecutionListener</interfacename>s should be
|
||
registered with the <classname>TestContextManager</classname>.
|
||
Typically, <interfacename>@TestExecutionListeners</interfacename> is
|
||
used in conjunction with
|
||
<interfacename>@ContextConfiguration</interfacename>.</para>
|
||
|
||
<programlisting language="java">@ContextConfiguration
|
||
<emphasis role="bold">@TestExecutionListeners</emphasis>({CustomTestExecutionListener.class, AnotherTestExecutionListener.class})
|
||
public class CustomTestExecutionListenerTests {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para><interfacename>@TestExecutionListeners</interfacename>
|
||
supports <emphasis>inherited</emphasis> listeners by default. See
|
||
the Javadoc for an example and further details.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@TransactionConfiguration</interfacename>
|
||
</emphasis></para>
|
||
|
||
<para>Defines class-level metadata for configuring transactional
|
||
tests. Specifically, the bean name of the
|
||
<interfacename>PlatformTransactionManager</interfacename> that
|
||
should be used to drive transactions can be explicitly specified if
|
||
there are multiple beans of type
|
||
<interfacename>PlatformTransactionManager</interfacename> in the
|
||
test's <interfacename>ApplicationContext</interfacename> and if the
|
||
bean name of the desired
|
||
<interfacename>PlatformTransactionManager</interfacename> is not
|
||
"transactionManager". In addition, you can change the
|
||
<literal>defaultRollback</literal> flag to <literal>false</literal>.
|
||
Typically, <interfacename>@TransactionConfiguration</interfacename>
|
||
is used in conjunction with
|
||
<interfacename>@ContextConfiguration</interfacename>.</para>
|
||
|
||
<programlisting language="java">@ContextConfiguration
|
||
<emphasis role="bold">@TransactionConfiguration</emphasis>(<emphasis role="bold">transactionManager</emphasis> = "txMgr", <emphasis
|
||
role="bold">defaultRollback</emphasis> = false)
|
||
public class CustomConfiguredTransactionalTests {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<note>
|
||
<para>If the default conventions are sufficient for your test
|
||
configuration, you can avoid using
|
||
<interfacename>@TransactionConfiguration</interfacename>
|
||
altogether. In other words, if you have only one transaction
|
||
manger — or if you have multiple transaction mangers but the
|
||
transaction manager for tests is named "transactionManager" or
|
||
specified via a
|
||
<interfacename>TransactionManagementConfigurer</interfacename> —
|
||
and if you want transactions to roll back automatically, then
|
||
there is no need to annotate your test class with
|
||
<interfacename>@TransactionConfiguration</interfacename>.</para>
|
||
</note>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@Rollback</interfacename> </emphasis></para>
|
||
|
||
<para>Indicates whether the transaction for the annotated test
|
||
method should be <emphasis>rolled back</emphasis> after the test
|
||
method has completed. If <literal>true</literal>, the transaction is
|
||
rolled back; otherwise, the transaction is committed. Use
|
||
<interfacename>@Rollback</interfacename> to override the default
|
||
rollback flag configured at the class level.</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@Rollback</emphasis>(false)
|
||
@Test
|
||
public void testProcessWithoutRollback() {
|
||
<lineannotation>// ...</lineannotation>
|
||
}</programlisting>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@BeforeTransaction</interfacename> </emphasis></para>
|
||
|
||
<para>Indicates that the annotated <literal>public void</literal>
|
||
method should be executed <emphasis>before</emphasis> a transaction
|
||
is started for test methods configured to run within a transaction
|
||
via the <interfacename>@Transactional</interfacename>
|
||
annotation.</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@BeforeTransaction
|
||
</emphasis>public void beforeTransaction() {
|
||
<lineannotation>// logic to be executed before a transaction is started</lineannotation>
|
||
}</programlisting>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@AfterTransaction</interfacename> </emphasis></para>
|
||
|
||
<para>Indicates that the annotated <literal>public void</literal>
|
||
method should be executed <emphasis>after</emphasis> a transaction
|
||
has ended for test methods configured to run within a transaction
|
||
via the <interfacename>@Transactional</interfacename>
|
||
annotation.</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@AfterTransaction
|
||
</emphasis>public void afterTransaction() {
|
||
<lineannotation>// logic to be executed after a transaction has ended</lineannotation>
|
||
}</programlisting>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@NotTransactional</interfacename> </emphasis></para>
|
||
|
||
<para>The presence of this annotation indicates that the annotated
|
||
test method must <emphasis>not</emphasis> execute in a transactional
|
||
context.</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@NotTransactional</emphasis>
|
||
@Test
|
||
public void testProcessWithoutTransaction() {
|
||
<lineannotation>// ...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<warning>
|
||
<title>@NotTransactional is deprecated</title>
|
||
|
||
<para>As of Spring 3.0,
|
||
<interfacename>@NotTransactional</interfacename> is deprecated in
|
||
favor of moving the <emphasis>non-transactional</emphasis> test
|
||
method to a separate (non-transactional) test class or to a
|
||
<interfacename>@BeforeTransaction</interfacename> or
|
||
<interfacename>@AfterTransaction</interfacename> method. As an
|
||
alternative to annotating an entire class with
|
||
<interfacename>@Transactional</interfacename>, consider annotating
|
||
individual methods with
|
||
<interfacename>@Transactional</interfacename>; doing so allows a
|
||
mix of transactional and non-transactional methods in the same
|
||
test class without the need for using
|
||
<interfacename>@NotTransactional</interfacename>.</para>
|
||
</warning>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</section>
|
||
|
||
<section xml:id="integration-testing-annotations-standard">
|
||
<title>Standard Annotation Support</title>
|
||
|
||
<para>The following annotations are supported with standard semantics
|
||
for all configurations of the Spring TestContext Framework. Note that
|
||
these annotations are not specific to tests and can be used anywhere in
|
||
the Spring Framework.</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@Autowired</interfacename> </emphasis></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@Qualifier</interfacename> </emphasis></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@Resource</interfacename> </emphasis>
|
||
(javax.annotation) <emphasis>if JSR-250 is present</emphasis></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold"> <interfacename>@Inject</interfacename>
|
||
</emphasis> (javax.inject) <emphasis>if JSR-330 is
|
||
present</emphasis></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold"> <interfacename>@Named</interfacename>
|
||
</emphasis> (javax.inject) <emphasis>if JSR-330 is
|
||
present</emphasis></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@PersistenceContext</interfacename> </emphasis>
|
||
(javax.persistence) <emphasis>if JPA is present</emphasis></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@PersistenceUnit</interfacename> </emphasis>
|
||
(javax.persistence) <emphasis>if JPA is present</emphasis></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@Required</interfacename> </emphasis></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@Transactional</interfacename> </emphasis></para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<note>
|
||
<title>JSR-250 Lifecycle Annotations</title>
|
||
|
||
<para>In the Spring TestContext Framework
|
||
<interfacename>@PostConstruct</interfacename> and
|
||
<interfacename>@PreDestroy</interfacename> may be used with standard
|
||
semantics on any application components configured in the
|
||
<interfacename>ApplicationContext</interfacename>; however, these
|
||
lifecycle annotations have limited usage within an actual test
|
||
class.</para>
|
||
|
||
<para>If a method within a test class is annotated with
|
||
<interfacename>@PostConstruct</interfacename>, that method will be
|
||
executed before any <emphasis>before</emphasis> methods of the
|
||
underlying test framework (e.g., methods annotated with JUnit's
|
||
<interfacename>@Before</interfacename>), and that will apply for every
|
||
test method in the test class. On the other hand, if a method within a
|
||
test class is annotated with
|
||
<interfacename>@PreDestroy</interfacename>, that method will <emphasis
|
||
role="bold">never</emphasis> be executed. Within a test class it is
|
||
therefore recommended to use test lifecycle callbacks from the
|
||
underlying test framework instead of
|
||
<interfacename>@PostConstruct</interfacename> and
|
||
<interfacename>@PreDestroy</interfacename>.</para>
|
||
</note>
|
||
</section>
|
||
|
||
<section xml:id="integration-testing-annotations-junit">
|
||
<title>Spring JUnit Testing Annotations</title>
|
||
|
||
<para>The following annotations are <emphasis>only</emphasis> supported
|
||
when used in conjunction with the <link
|
||
linkend="testcontext-junit4-runner">SpringJUnit4ClassRunner</link> or
|
||
the <link linkend="testcontext-support-classes-junit4">JUnit</link>
|
||
support classes.</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@IfProfileValue</interfacename> </emphasis></para>
|
||
|
||
<para>Indicates that the annotated test is enabled for a specific
|
||
testing environment. If the configured
|
||
<classname>ProfileValueSource</classname> returns a matching
|
||
<literal>value</literal> for the provided <literal>name</literal>,
|
||
the test is enabled. This annotation can be applied to an entire
|
||
class or to individual methods. Class-level usage overrides
|
||
method-level usage.</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@IfProfileValue</emphasis>(<emphasis
|
||
role="bold">name</emphasis>="java.vendor", <emphasis role="bold">value</emphasis>="Sun Microsystems Inc.")
|
||
@Test
|
||
public void testProcessWhichRunsOnlyOnSunJvm() {
|
||
<lineannotation>// some logic that should run only on Java VMs from Sun Microsystems</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para>Alternatively, you can configure
|
||
<interfacename>@IfProfileValue</interfacename> with a list of
|
||
<literal>values</literal> (with <emphasis>OR</emphasis> semantics)
|
||
to achieve TestNG-like support for <emphasis>test groups</emphasis>
|
||
in a JUnit environment. Consider the following example:</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@IfProfileValue</emphasis>(<emphasis
|
||
role="bold">name</emphasis>="test-groups", <emphasis role="bold">values</emphasis>={"unit-tests", "integration-tests"})
|
||
@Test
|
||
public void testProcessWhichRunsForUnitOrIntegrationTestGroups() {
|
||
<lineannotation>// some logic that should run only for unit and integration test groups</lineannotation>
|
||
}</programlisting>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold">
|
||
<interfacename>@ProfileValueSourceConfiguration</interfacename>
|
||
</emphasis></para>
|
||
|
||
<para>Class-level annotation that specifies what type of
|
||
<literal>ProfileValueSource</literal> to use when retrieving
|
||
<emphasis>profile values</emphasis> configured through the
|
||
<interfacename>@IfProfileValue</interfacename> annotation. If
|
||
<interfacename>@ProfileValueSourceConfiguration</interfacename> is
|
||
not declared for a test,
|
||
<classname>SystemProfileValueSource</classname> is used by
|
||
default.</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@ProfileValueSourceConfiguration</emphasis>(CustomProfileValueSource.class)
|
||
public class CustomProfileValueSourceTests {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold"> <interfacename>@Timed</interfacename>
|
||
</emphasis></para>
|
||
|
||
<para>Indicates that the annotated test method must finish execution
|
||
in a specified time period (in milliseconds). If the text execution
|
||
time exceeds the specified time period, the test fails.</para>
|
||
|
||
<para>The time period includes execution of the test method itself,
|
||
any repetitions of the test (see
|
||
<interfacename>@Repeat</interfacename>), as well as any
|
||
<emphasis>set up</emphasis> or <emphasis>tear down</emphasis> of the
|
||
test fixture.</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@Timed</emphasis>(millis=1000)
|
||
public void testProcessWithOneSecondTimeout() {
|
||
<lineannotation>// some logic that should not take longer than 1 second to execute</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para>Spring's <interfacename>@Timed</interfacename> annotation has
|
||
different semantics than JUnit's
|
||
<interfacename>@Test(timeout=...)</interfacename> support.
|
||
Specifically, due to the manner in which JUnit handles test
|
||
execution timeouts (that is, by executing the test method in a
|
||
separate <classname>Thread</classname>),
|
||
<interfacename>@Test(timeout=...)</interfacename> applies to
|
||
<emphasis>each iteration</emphasis> in the case of repetitions and
|
||
preemptively fails the test if the test takes too long. Spring's
|
||
<interfacename>@Timed</interfacename>, on the other hand, times the
|
||
<emphasis>total</emphasis> test execution time (including all
|
||
repetitions) and does not preemptively fail the test but rather
|
||
waits for the test to complete before failing.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><emphasis role="bold"> <interfacename>@Repeat</interfacename>
|
||
</emphasis></para>
|
||
|
||
<para>Indicates that the annotated test method must be executed
|
||
repeatedly. The number of times that the test method is to be
|
||
executed is specified in the annotation.</para>
|
||
|
||
<para>The scope of execution to be repeated includes execution of
|
||
the test method itself as well as any <emphasis>set up</emphasis> or
|
||
<emphasis>tear down</emphasis> of the test fixture.</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@Repeat</emphasis>(10)
|
||
@Test
|
||
public void testProcessRepeatedly() {
|
||
<lineannotation>// ...</lineannotation>
|
||
}</programlisting>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</section>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-framework">
|
||
<title>Spring TestContext Framework</title>
|
||
|
||
<para>The <emphasis>Spring <classname>TestContext</classname>
|
||
Framework</emphasis> (located in the
|
||
<literal>org.springframework.test.context</literal> package) provides
|
||
generic, annotation-driven unit and integration testing support that is
|
||
agnostic of the testing framework in use. The TestContext framework also
|
||
places a great deal of importance on <emphasis>convention over
|
||
configuration</emphasis> with reasonable defaults that can be overridden
|
||
through annotation-based configuration.</para>
|
||
|
||
<para>In addition to generic testing infrastructure, the TestContext
|
||
framework provides explicit support for JUnit and TestNG in the form of
|
||
<literal>abstract</literal> support classes. For JUnit, Spring also
|
||
provides a custom JUnit <interfacename>Runner</interfacename> that allows
|
||
one to write so-called <emphasis>POJO test classes</emphasis>. POJO test
|
||
classes are not required to extend a particular class hierarchy.</para>
|
||
|
||
<para>The following section provides an overview of the internals of the
|
||
TestContext framework. If you are only interested in using the framework
|
||
and not necessarily interested in extending it with your own custom
|
||
listeners or custom loaders, feel free to go directly to the configuration
|
||
(<link linkend="testcontext-ctx-management">context management</link>,
|
||
<link linkend="testcontext-fixture-di">dependency injection</link>, <link
|
||
linkend="testcontext-tx">transaction management</link>), <link
|
||
linkend="testcontext-support-classes">support classes</link>, and <link
|
||
linkend="integration-testing-annotations">annotation support</link>
|
||
sections.</para>
|
||
|
||
<section xml:id="testcontext-key-abstractions">
|
||
<title>Key abstractions</title>
|
||
|
||
<para>The core of the framework consists of the
|
||
<classname>TestContext</classname> and
|
||
<classname>TestContextManager</classname> classes and the
|
||
<interfacename>TestExecutionListener</interfacename>,
|
||
<interfacename>ContextLoader</interfacename>, and
|
||
<interfacename>SmartContextLoader</interfacename> interfaces. A
|
||
<classname>TestContextManager</classname> is created on a per-test basis
|
||
(e.g., for the execution of a single test method in JUnit). The
|
||
<classname>TestContextManager</classname> in turn manages a
|
||
<classname>TestContext</classname> that holds the context of the current
|
||
test. The <classname>TestContextManager</classname> also updates the
|
||
state of the <classname>TestContext</classname> as the test progresses
|
||
and delegates to <interfacename>TestExecutionListener</interfacename>s,
|
||
which instrument the actual test execution by providing dependency
|
||
injection, managing transactions, and so on. A
|
||
<interfacename>ContextLoader</interfacename> (or
|
||
<interfacename>SmartContextLoader</interfacename>) is responsible for
|
||
loading an <interfacename>ApplicationContext</interfacename> for a given
|
||
test class. Consult the Javadoc and the Spring test suite for further
|
||
information and examples of various implementations.</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><classname>TestContext</classname>: Encapsulates the context
|
||
in which a test is executed, agnostic of the actual testing
|
||
framework in use, and provides context management and caching
|
||
support for the test instance for which it is responsible. The
|
||
<classname>TestContext</classname> also delegates to a
|
||
<interfacename>ContextLoader</interfacename> (or
|
||
<interfacename>SmartContextLoader</interfacename>) to load an
|
||
<interfacename>ApplicationContext</interfacename> if
|
||
requested.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><classname>TestContextManager</classname>: The main entry
|
||
point into the <emphasis>Spring TestContext Framework</emphasis>,
|
||
which manages a single <classname>TestContext</classname> and
|
||
signals events to all registered
|
||
<interfacename>TestExecutionListener</interfacename>s at
|
||
well-defined test execution points:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>prior to any <emphasis>before class methods</emphasis> of
|
||
a particular testing framework</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>test instance preparation</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>prior to any <emphasis>before methods</emphasis> of a
|
||
particular testing framework</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>after any <emphasis>after methods</emphasis> of a
|
||
particular testing framework</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>after any <emphasis>after class methods</emphasis> of a
|
||
particular testing framework</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><interfacename>TestExecutionListener</interfacename>: Defines
|
||
a <emphasis>listener</emphasis> API for reacting to test execution
|
||
events published by the <classname>TestContextManager</classname>
|
||
with which the listener is registered.</para>
|
||
|
||
<para>Spring provides four
|
||
<interfacename>TestExecutionListener</interfacename> implementations
|
||
that are configured by default:
|
||
<classname>ServletTestExecutionListener</classname>,
|
||
<classname>DependencyInjectionTestExecutionListener</classname>,
|
||
<classname>DirtiesContextTestExecutionListener</classname>, and
|
||
<classname>TransactionalTestExecutionListener</classname>.
|
||
Respectively, they support Servlet API mocks for a
|
||
<interfacename>WebApplicationContext</interfacename>, dependency
|
||
injection of the test instance, handling of the
|
||
<interfacename>@DirtiesContext</interfacename> annotation, and
|
||
transactional test execution with default rollback semantics.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><interfacename>ContextLoader</interfacename>: Strategy
|
||
interface introduced in Spring 2.5 for loading an
|
||
<interfacename>ApplicationContext</interfacename> for an integration
|
||
test managed by the Spring TestContext Framework.</para>
|
||
|
||
<para>As of Spring 3.1, implement
|
||
<interfacename>SmartContextLoader</interfacename> instead of this
|
||
interface in order to provide support for annotated classes and
|
||
active bean definition profiles.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><interfacename>SmartContextLoader</interfacename>: Extension
|
||
of the <interfacename>ContextLoader</interfacename> interface
|
||
introduced in Spring 3.1.</para>
|
||
|
||
<para>The <interfacename>SmartContextLoader</interfacename> SPI
|
||
supersedes the <interfacename>ContextLoader</interfacename> SPI that
|
||
was introduced in Spring 2.5. Specifically, a
|
||
<interfacename>SmartContextLoader</interfacename> can choose to
|
||
process resource <varname>locations</varname>, annotated
|
||
<varname>classes</varname>, or context
|
||
<varname>initializers</varname>. Furthermore, a
|
||
<interfacename>SmartContextLoader</interfacename> can set active
|
||
bean definition profiles in the context that it loads.</para>
|
||
|
||
<para>Spring provides the following implementations:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><classname>DelegatingSmartContextLoader</classname>: one
|
||
of two default loaders which delegates internally to an
|
||
<classname>AnnotationConfigContextLoader</classname> or a
|
||
<classname>GenericXmlContextLoader</classname> depending either
|
||
on the configuration declared for the test class or on the
|
||
presence of default locations or default configuration
|
||
classes.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><classname>WebDelegatingSmartContextLoader</classname>:
|
||
one of two default loaders which delegates internally to an
|
||
<classname>AnnotationConfigWebContextLoader</classname> or a
|
||
<classname>GenericXmlWebContextLoader</classname> depending
|
||
either on the configuration declared for the test class or on
|
||
the presence of default locations or default configuration
|
||
classes. A web <interfacename>ContextLoader</interfacename> will
|
||
only be used if
|
||
<interfacename>@WebAppConfiguration</interfacename> is present
|
||
on the test class.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><classname>AnnotationConfigContextLoader</classname>:
|
||
loads a standard
|
||
<interfacename>ApplicationContext</interfacename> from
|
||
<emphasis>annotated classes</emphasis>.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><classname>AnnotationConfigWebContextLoader</classname>:
|
||
loads a <interfacename>WebApplicationContext</interfacename>
|
||
from <emphasis>annotated classes</emphasis>.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><classname>GenericXmlContextLoader</classname>: loads a
|
||
standard <interfacename>ApplicationContext</interfacename> from
|
||
XML <emphasis>resource locations</emphasis>.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><classname>GenericXmlWebContextLoader</classname>: loads a
|
||
<interfacename>WebApplicationContext</interfacename> from XML
|
||
<emphasis>resource locations</emphasis>.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><classname>GenericPropertiesContextLoader</classname>:
|
||
loads a standard
|
||
<interfacename>ApplicationContext</interfacename> from Java
|
||
Properties files.</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<para>The following sections explain how to configure the
|
||
<classname>TestContext</classname> framework through annotations and
|
||
provide working examples of how to write unit and integration tests with
|
||
the framework.</para>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-ctx-management">
|
||
<title>Context management</title>
|
||
|
||
<para>Each <classname>TestContext</classname> provides context
|
||
management and caching support for the test instance it is responsible
|
||
for. Test instances do not automatically receive access to the
|
||
configured <interfacename>ApplicationContext</interfacename>. However,
|
||
if a test class implements the
|
||
<interfacename>ApplicationContextAware</interfacename> interface, a
|
||
reference to the <classname>ApplicationContext</classname> is supplied
|
||
to the test instance. Note that
|
||
<classname>AbstractJUnit4SpringContextTests</classname> and
|
||
<classname>AbstractTestNGSpringContextTests</classname> implement
|
||
<interfacename>ApplicationContextAware</interfacename> and therefore
|
||
provide access to the <classname>ApplicationContext</classname>
|
||
automatically.</para>
|
||
|
||
<tip>
|
||
<title>@Autowired ApplicationContext</title>
|
||
|
||
<para>As an alternative to implementing the
|
||
<interfacename>ApplicationContextAware</interfacename> interface, you
|
||
can inject the application context for your test class through the
|
||
<interfacename>@Autowired</interfacename> annotation on either a field
|
||
or setter method. For example:</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
@ContextConfiguration
|
||
public class MyTest {
|
||
|
||
<emphasis role="bold">@Autowired</emphasis>
|
||
private ApplicationContext applicationContext;
|
||
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para>Similarly, if your test is configured to load a
|
||
<interfacename>WebApplicationContext</interfacename>, you can inject
|
||
the web application context into your test as follows:</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
<emphasis role="bold">@WebAppConfiguration</emphasis>
|
||
@ContextConfiguration
|
||
public class MyWebAppTest {
|
||
|
||
<emphasis role="bold">@Autowired</emphasis>
|
||
private WebApplicationContext wac;
|
||
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para>Dependency injection via
|
||
<interfacename>@Autowired</interfacename> is provided by the
|
||
<classname>DependencyInjectionTestExecutionListener</classname> which
|
||
is configured by default (see <xref
|
||
linkend="testcontext-fixture-di"/>).</para>
|
||
</tip>
|
||
|
||
<para>Test classes that use the TestContext framework do not need to
|
||
extend any particular class or implement a specific interface to
|
||
configure their application context. Instead, configuration is achieved
|
||
simply by declaring the
|
||
<interfacename>@ContextConfiguration</interfacename> annotation at the
|
||
class level. If your test class does not explicitly declare application
|
||
context resource <literal>locations</literal> or annotated
|
||
<varname>classes</varname>, the configured
|
||
<interfacename>ContextLoader</interfacename> determines how to load a
|
||
context from a default location or default configuration classes. In
|
||
addition to context resource <varname>locations</varname> and annotated
|
||
<varname>classes</varname>, an application context can also be
|
||
configured via application context
|
||
<varname>initializers</varname>.</para>
|
||
|
||
<para>The following sections explain how to configure an
|
||
<interfacename>ApplicationContext</interfacename> via XML configuration
|
||
files, annotated classes (typically
|
||
<interfacename>@Configuration</interfacename> classes), or context
|
||
initializers using Spring's
|
||
<interfacename>@ContextConfiguration</interfacename> annotation.
|
||
Alternatively, you can implement and configure your own custom
|
||
<interfacename>SmartContextLoader</interfacename> for advanced use
|
||
cases.</para>
|
||
|
||
<section xml:id="testcontext-ctx-management-xml">
|
||
<title>Context configuration with XML resources</title>
|
||
|
||
<para>To load an <interfacename>ApplicationContext</interfacename> for
|
||
your tests using XML configuration files, annotate your test class
|
||
with <interfacename>@ContextConfiguration</interfacename> and
|
||
configure the <literal>locations</literal> attribute with an array
|
||
that contains the resource locations of XML configuration metadata. A
|
||
plain or relative path — for example <literal>"context.xml"</literal>
|
||
— will be treated as a classpath resource that is relative to the
|
||
package in which the test class is defined. A path starting with a
|
||
slash is treated as an absolute classpath location, for example
|
||
<literal>"/org/example/config.xml"</literal>. A path which represents
|
||
a resource URL (i.e., a path prefixed with
|
||
<literal>classpath:</literal>, <literal>file:</literal>,
|
||
<literal>http:</literal>, etc.) will be used <emphasis>as
|
||
is</emphasis>.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
<lineannotation>// ApplicationContext will be loaded from "/app-config.xml" and
|
||
// "/test-config.xml" in the root of the classpath</lineannotation>
|
||
<emphasis role="bold">@ContextConfiguration(locations={"/app-config.xml", "/test-config.xml"})</emphasis>
|
||
public class MyTest {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para><interfacename>@ContextConfiguration</interfacename> supports an
|
||
alias for the <literal>locations</literal> attribute through the
|
||
standard Java <literal>value</literal> attribute. Thus, if you do not
|
||
need to declare additional attributes in
|
||
<interfacename>@ContextConfiguration</interfacename>, you can omit the
|
||
declaration of the <literal>locations</literal> attribute name and
|
||
declare the resource locations by using the shorthand format
|
||
demonstrated in the following example.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
<emphasis role="bold">@ContextConfiguration({"/app-config.xml", "/test-config.xml"})</emphasis>
|
||
public class MyTest {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para>If you omit both the <varname>locations</varname> and
|
||
<varname>value</varname> attributes from the
|
||
<interfacename>@ContextConfiguration</interfacename> annotation, the
|
||
TestContext framework will attempt to detect a default XML resource
|
||
location. Specifically, <classname>GenericXmlContextLoader</classname>
|
||
detects a default location based on the name of the test class. If
|
||
your class is named <literal>com.example.MyTest</literal>,
|
||
<classname>GenericXmlContextLoader</classname> loads your application
|
||
context from
|
||
<literal>"classpath:/com/example/MyTest-context.xml"</literal>.</para>
|
||
|
||
<programlisting language="java">package com.example;
|
||
|
||
@RunWith(SpringJUnit4ClassRunner.class)
|
||
<lineannotation>// ApplicationContext will be loaded from
|
||
// "classpath:/com/example/MyTest-context.xml"</lineannotation>
|
||
<emphasis role="bold">@ContextConfiguration</emphasis>
|
||
public class MyTest {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-ctx-management-javaconfig">
|
||
<title>Context configuration with annotated classes</title>
|
||
|
||
<para>To load an <interfacename>ApplicationContext</interfacename> for
|
||
your tests using <emphasis>annotated classes</emphasis> (see <xref
|
||
linkend="beans-java"/>), annotate your test class with
|
||
<interfacename>@ContextConfiguration</interfacename> and configure the
|
||
<literal>classes</literal> attribute with an array that contains
|
||
references to annotated classes.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
<lineannotation>// ApplicationContext will be loaded from AppConfig and TestConfig</lineannotation>
|
||
<emphasis role="bold">@ContextConfiguration(classes = {AppConfig.class, TestConfig.class})</emphasis>
|
||
public class MyTest {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para>If you omit the <varname>classes</varname> attribute from the
|
||
<interfacename>@ContextConfiguration</interfacename> annotation, the
|
||
TestContext framework will attempt to detect the presence of default
|
||
configuration classes. Specifically,
|
||
<classname>AnnotationConfigContextLoader</classname> will detect all
|
||
static inner classes of the test class that meet the requirements for
|
||
configuration class implementations as specified in the Javadoc for
|
||
<interfacename>@Configuration</interfacename>. In the following
|
||
example, the <classname>OrderServiceTest</classname> class declares a
|
||
static inner configuration class named <classname>Config</classname>
|
||
that will be automatically used to load the
|
||
<interfacename>ApplicationContext</interfacename> for the test class.
|
||
Note that the name of the configuration class is arbitrary. In
|
||
addition, a test class can contain more than one static inner
|
||
configuration class if desired.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
<lineannotation>// ApplicationContext will be loaded from the
|
||
// static inner Config class</lineannotation>
|
||
<emphasis role="bold">@ContextConfiguration</emphasis>
|
||
public class OrderServiceTest {
|
||
|
||
@Configuration
|
||
static class Config {
|
||
|
||
<lineannotation>// this bean will be injected into the OrderServiceTest class</lineannotation>
|
||
@Bean
|
||
public OrderService orderService() {
|
||
OrderService orderService = new OrderServiceImpl();
|
||
<lineannotation>// set properties, etc.</lineannotation>
|
||
return orderService;
|
||
}
|
||
}
|
||
|
||
@Autowired
|
||
private OrderService orderService;
|
||
|
||
@Test
|
||
public void testOrderService() {
|
||
<lineannotation>// test the orderService</lineannotation>
|
||
}
|
||
|
||
}</programlisting>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-ctx-management-mixed-config">
|
||
<title>Mixing XML resources and annotated classes</title>
|
||
|
||
<para>It may sometimes be desirable to mix XML resources and annotated
|
||
classes (i.e., typically <interfacename>@Configuration</interfacename>
|
||
classes) to configure an
|
||
<interfacename>ApplicationContext</interfacename> for your tests. For
|
||
example, if you use XML configuration in production, you may decide
|
||
that you want to use <interfacename>@Configuration</interfacename>
|
||
classes to configure specific Spring-managed components for your
|
||
tests, or vice versa. As mentioned in <xref
|
||
linkend="integration-testing-annotations-spring"/> the TestContext
|
||
framework does not allow you to declare <emphasis>both</emphasis> via
|
||
<interfacename>@ContextConfiguration</interfacename>, but this does
|
||
not mean that you cannot use both.</para>
|
||
|
||
<para>If you want to use XML <emphasis role="bold">and</emphasis>
|
||
<interfacename>@Configuration</interfacename> classes to configure
|
||
your tests, you will have to pick one as the <emphasis>entry
|
||
point</emphasis>, and that one will have to include or import the
|
||
other. For example, in XML you can include
|
||
<interfacename>@Configuration</interfacename> classes via component
|
||
scanning or define them as normal Spring beans in XML; whereas, in a
|
||
<interfacename>@Configuration</interfacename> class you can use
|
||
<interfacename>@ImportResource</interfacename> to import XML
|
||
configuration files. Note that this behavior is semantically
|
||
equivalent to how you configure your application in production: in
|
||
production configuration you will define either a set of XML resource
|
||
locations or a set of <interfacename>@Configuration</interfacename>
|
||
classes that your production
|
||
<interfacename>ApplicationContext</interfacename> will be loaded from,
|
||
but you still have the freedom to include or import the other type of
|
||
configuration.</para>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-ctx-management-initializers">
|
||
<title>Context configuration with context initializers</title>
|
||
|
||
<para>To configure an
|
||
<interfacename>ApplicationContext</interfacename> for your tests using
|
||
context initializers, annotate your test class with
|
||
<interfacename>@ContextConfiguration</interfacename> and configure the
|
||
<literal>initializers</literal> attribute with an array that contains
|
||
references to classes that implement
|
||
<interfacename>ApplicationContextInitializer</interfacename>. The
|
||
declared context initializers will then be used to initialize the
|
||
<interfacename>ConfigurableApplicationContext</interfacename> that is
|
||
loaded for your tests. Note that the concrete
|
||
<interfacename>ConfigurableApplicationContext</interfacename> type
|
||
supported by each declared initializer must be compatible with the
|
||
type of <interfacename>ApplicationContext</interfacename> created by
|
||
the <interfacename>SmartContextLoader</interfacename> in use (i.e.,
|
||
typically a <classname>GenericApplicationContext</classname>).
|
||
Furthermore, the order in which the initializers are invoked depends
|
||
on whether they implement Spring's
|
||
<interfacename>Ordered</interfacename> interface or are annotated with
|
||
Spring's <interfacename>@Order</interfacename> annotation.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
<lineannotation>// ApplicationContext will be loaded from TestConfig
|
||
</lineannotation><lineannotation>// and initialized by TestAppCtxInitializer</lineannotation>
|
||
<emphasis role="bold">@ContextConfiguration(
|
||
classes = TestConfig.class,
|
||
initializers = TestAppCtxInitializer.class)</emphasis>
|
||
public class MyTest {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para>It is also possible to omit the declaration of XML configuration
|
||
files or annotated classes in
|
||
<interfacename>@ContextConfiguration</interfacename> entirely and
|
||
instead declare only
|
||
<interfacename>ApplicationContextInitializer</interfacename> classes
|
||
which are then responsible for registering beans in the context — for
|
||
example, by programmatically loading bean definitions from XML files
|
||
or configuration classes.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
<lineannotation>// ApplicationContext will be initialized by EntireAppInitializer
|
||
</lineannotation><lineannotation>// which presumably registers beans in the context</lineannotation>
|
||
<emphasis role="bold">@ContextConfiguration(initializers = EntireAppInitializer.class)</emphasis>
|
||
public class MyTest {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-ctx-management-inheritance">
|
||
<title>Context configuration inheritance</title>
|
||
|
||
<para><interfacename>@ContextConfiguration</interfacename> supports
|
||
boolean <varname>inheritLocations</varname> and
|
||
<varname>inheritInitializers</varname> attributes that denote whether
|
||
resource locations or annotated classes and context initializers
|
||
declared by superclasses should be <emphasis>inherited</emphasis>. The
|
||
default value for both flags is <literal>true</literal>. This means
|
||
that a test class inherits the resource locations or annotated classes
|
||
as well as the context initializers declared by any superclasses.
|
||
Specifically, the resource locations or annotated classes for a test
|
||
class are appended to the list of resource locations or annotated
|
||
classes declared by superclasses. Similarly, the initializers for a
|
||
given test class will be added to the set of initializers defined by
|
||
test superclasses. Thus, subclasses have the option of
|
||
<emphasis>extending</emphasis> the resource locations, annotated
|
||
classes, or context initializers.</para>
|
||
|
||
<para>If <interfacename>@ContextConfiguration</interfacename>'s
|
||
<literal>inheritLocations</literal> or
|
||
<varname>inheritInitializers</varname> attribute is set to
|
||
<literal>false</literal>, the resource locations or annotated classes
|
||
and the context initializers, respectively, for the test class
|
||
<emphasis>shadow</emphasis> and effectively replace the configuration
|
||
defined by superclasses.</para>
|
||
|
||
<para>In the following example that uses XML resource locations, the
|
||
<interfacename>ApplicationContext</interfacename> for
|
||
<classname>ExtendedTest</classname> will be loaded from
|
||
<emphasis>"base-config.xml"</emphasis> <emphasis
|
||
role="bold">and</emphasis> <emphasis>"extended-config.xml"</emphasis>,
|
||
in that order. Beans defined in
|
||
<emphasis>"extended-config.xml"</emphasis> may therefore
|
||
<emphasis>override</emphasis> (i.e., replace) those defined in
|
||
<emphasis>"base-config.xml"</emphasis>.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
<lineannotation>// ApplicationContext will be loaded from "/base-config.xml"
|
||
// in the root of the classpath</lineannotation>
|
||
<emphasis role="bold">@ContextConfiguration("/base-config.xml")</emphasis>
|
||
public class BaseTest {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}
|
||
|
||
<lineannotation>// ApplicationContext will be loaded from "/base-config.xml" and
|
||
// "/extended-config.xml" </lineannotation><lineannotation>in the root of the classpath</lineannotation>
|
||
<emphasis role="bold">@ContextConfiguration("/extended-config.xml")</emphasis>
|
||
public class ExtendedTest extends BaseTest {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para>Similarly, in the following example that uses annotated classes,
|
||
the <interfacename>ApplicationContext</interfacename> for
|
||
<classname>ExtendedTest</classname> will be loaded from the
|
||
<classname>BaseConfig</classname> <emphasis role="bold">and</emphasis>
|
||
<classname>ExtendedConfig</classname> classes, in that order. Beans
|
||
defined in <classname>ExtendedConfig</classname> may therefore
|
||
override (i.e., replace) those defined in
|
||
<classname>BaseConfig</classname>.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
<lineannotation>// ApplicationContext will be loaded from BaseConfig</lineannotation>
|
||
<emphasis role="bold">@ContextConfiguration(classes = BaseConfig.class)</emphasis>
|
||
public class BaseTest {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}
|
||
|
||
<lineannotation>// ApplicationContext will be loaded from BaseConfig and ExtendedConfig</lineannotation>
|
||
<emphasis role="bold">@ContextConfiguration(classes = ExtendedConfig.class)</emphasis>
|
||
public class ExtendedTest extends BaseTest {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para>In the following example that uses context initializers, the
|
||
<interfacename>ApplicationContext</interfacename> for
|
||
<classname>ExtendedTest</classname> will be initialized using
|
||
<classname>BaseInitializer</classname> <emphasis
|
||
role="bold">and</emphasis> <classname>ExtendedInitializer</classname>.
|
||
Note, however, that the order in which the initializers are invoked
|
||
depends on whether they implement Spring's
|
||
<interfacename>Ordered</interfacename> interface or are annotated with
|
||
Spring's <interfacename>@Order</interfacename> annotation.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
<lineannotation>// ApplicationContext will be initialized by BaseInitializer</lineannotation>
|
||
<emphasis role="bold">@ContextConfiguration(initializers=BaseInitializer.class)</emphasis>
|
||
public class BaseTest {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}
|
||
|
||
<lineannotation>// ApplicationContext will be initialized by BaseInitializer
|
||
// and ExtendedInitializer</lineannotation>
|
||
<emphasis role="bold">@ContextConfiguration(initializers=ExtendedInitializer.class)</emphasis>
|
||
public class ExtendedTest extends BaseTest {
|
||
<lineannotation>// class body...</lineannotation>
|
||
}</programlisting>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-ctx-management-env-profiles">
|
||
<title>Context configuration with environment profiles</title>
|
||
|
||
<para>Spring 3.1 introduced first-class support in the framework for
|
||
the notion of environments and profiles (a.k.a., <emphasis>bean
|
||
definition profiles</emphasis>), and integration tests can be
|
||
configured to activate particular bean definition profiles for various
|
||
testing scenarios. This is achieved by annotating a test class with
|
||
the <interfacename>@ActiveProfiles</interfacename> annotation and
|
||
supplying a list of profiles that should be activated when loading the
|
||
<interfacename>ApplicationContext</interfacename> for the test.</para>
|
||
|
||
<note>
|
||
<para><interfacename>@ActiveProfiles</interfacename> may be used
|
||
with any implementation of the new
|
||
<interfacename>SmartContextLoader</interfacename> SPI, but
|
||
<interfacename>@ActiveProfiles</interfacename> is not supported with
|
||
implementations of the older
|
||
<interfacename>ContextLoader</interfacename> SPI.</para>
|
||
</note>
|
||
|
||
<para>Let's take a look at some examples with XML configuration and
|
||
<interfacename>@Configuration</interfacename> classes.</para>
|
||
|
||
<programlisting language="xml"><!-- app-config.xml -->
|
||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||
xmlns:jee="http://www.springframework.org/schema/jee"
|
||
xsi:schemaLocation="...">
|
||
|
||
<bean id="transferService"
|
||
class="com.bank.service.internal.DefaultTransferService">
|
||
<constructor-arg ref="accountRepository"/>
|
||
<constructor-arg ref="feePolicy"/>
|
||
</bean>
|
||
|
||
<bean id="accountRepository"
|
||
class="com.bank.repository.internal.JdbcAccountRepository">
|
||
<constructor-arg ref="dataSource"/>
|
||
</bean>
|
||
|
||
<bean id="feePolicy"
|
||
class="com.bank.service.internal.ZeroFeePolicy"/>
|
||
|
||
<beans profile="dev">
|
||
<jdbc:embedded-database id="dataSource">
|
||
<jdbc:script
|
||
location="classpath:com/bank/config/sql/schema.sql"/>
|
||
<jdbc:script
|
||
location="classpath:com/bank/config/sql/test-data.sql"/>
|
||
</jdbc:embedded-database>
|
||
</beans>
|
||
|
||
<beans profile="production">
|
||
<jee:jndi-lookup id="dataSource"
|
||
jndi-name="java:comp/env/jdbc/datasource"/>
|
||
</beans>
|
||
|
||
</beans></programlisting>
|
||
|
||
<programlisting language="java">package com.bank.service;
|
||
|
||
@RunWith(SpringJUnit4ClassRunner.class)
|
||
// ApplicationContext will be loaded from "classpath:/app-config.xml"
|
||
@ContextConfiguration("/app-config.xml")
|
||
@ActiveProfiles("dev")
|
||
public class TransferServiceTest {
|
||
|
||
@Autowired
|
||
private TransferService transferService;
|
||
|
||
@Test
|
||
public void testTransferService() {
|
||
// test the transferService
|
||
}
|
||
}</programlisting>
|
||
|
||
<para>When <classname>TransferServiceTest</classname> is run, its
|
||
<interfacename>ApplicationContext</interfacename> will be loaded from
|
||
the <filename>app-config.xml</filename> configuration file in the root
|
||
of the classpath. If you inspect <filename>app-config.xml</filename>
|
||
you'll notice that the <varname>accountRepository</varname> bean has a
|
||
dependency on a <varname>dataSource</varname> bean; however,
|
||
<varname>dataSource</varname> is not defined as a top-level bean.
|
||
Instead, <varname>dataSource</varname> is defined twice: once in the
|
||
<emphasis>production</emphasis> profile and once in the
|
||
<emphasis>dev</emphasis> profile.</para>
|
||
|
||
<para>By annotating <classname>TransferServiceTest</classname> with
|
||
<interfacename>@ActiveProfiles("dev")</interfacename> we instruct the
|
||
Spring TestContext Framework to load the
|
||
<interfacename>ApplicationContext</interfacename> with the active
|
||
profiles set to <literal>{"dev"}</literal>. As a result, an embedded
|
||
database will be created, and the <varname>accountRepository</varname>
|
||
bean will be wired with a reference to the development
|
||
<interfacename>DataSource</interfacename>. And that's likely what we
|
||
want in an integration test.</para>
|
||
|
||
<para>The following code listings demonstrate how to implement the
|
||
same configuration and integration test but using
|
||
<interfacename>@Configuration</interfacename> classes instead of
|
||
XML.</para>
|
||
|
||
<programlisting language="java">@Configuration
|
||
@Profile("dev")
|
||
public class StandaloneDataConfig {
|
||
|
||
@Bean
|
||
public DataSource dataSource() {
|
||
return new EmbeddedDatabaseBuilder()
|
||
.setType(EmbeddedDatabaseType.HSQL)
|
||
.addScript("classpath:com/bank/config/sql/schema.sql")
|
||
.addScript("classpath:com/bank/config/sql/test-data.sql")
|
||
.build();
|
||
}
|
||
}</programlisting>
|
||
|
||
<programlisting language="java">@Configuration
|
||
@Profile("production")
|
||
public class JndiDataConfig {
|
||
|
||
@Bean
|
||
public DataSource dataSource() throws Exception {
|
||
Context ctx = new InitialContext();
|
||
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
|
||
}
|
||
}</programlisting>
|
||
|
||
<programlisting language="java">@Configuration
|
||
public class TransferServiceConfig {
|
||
|
||
@Autowired DataSource dataSource;
|
||
|
||
@Bean
|
||
public TransferService transferService() {
|
||
return new DefaultTransferService(accountRepository(),
|
||
feePolicy());
|
||
}
|
||
|
||
@Bean
|
||
public AccountRepository accountRepository() {
|
||
return new JdbcAccountRepository(dataSource);
|
||
}
|
||
|
||
@Bean
|
||
public FeePolicy feePolicy() {
|
||
return new ZeroFeePolicy();
|
||
}
|
||
|
||
}</programlisting>
|
||
|
||
<programlisting language="java">package com.bank.service;
|
||
|
||
@RunWith(SpringJUnit4ClassRunner.class)
|
||
@ContextConfiguration(
|
||
classes = {
|
||
TransferServiceConfig.class,
|
||
StandaloneDataConfig.class,
|
||
JndiDataConfig.class})
|
||
@ActiveProfiles("dev")
|
||
public class TransferServiceTest {
|
||
|
||
@Autowired
|
||
private TransferService transferService;
|
||
|
||
@Test
|
||
public void testTransferService() {
|
||
// test the transferService
|
||
}
|
||
}</programlisting>
|
||
|
||
<para>In this variation, we have split the XML configuration into
|
||
three independent <interfacename>@Configuration</interfacename>
|
||
classes:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><classname>TransferServiceConfig</classname>: acquires a
|
||
<varname>dataSource</varname> via dependency injection using
|
||
<interfacename>@Autowired</interfacename></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><classname>StandaloneDataConfig</classname>: defines a
|
||
<varname>dataSource</varname> for an embedded database suitable
|
||
for developer tests</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><classname>JndiDataConfig</classname>: defines a
|
||
<varname>dataSource</varname> that is retrieved from JNDI in a
|
||
production environment</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<para>As with the XML-based configuration example, we still annotate
|
||
<classname>TransferServiceTest</classname> with
|
||
<interfacename>@ActiveProfiles("dev")</interfacename>, but this time
|
||
we specify all three configuration classes via the
|
||
<interfacename>@ContextConfiguration </interfacename>annotation. The
|
||
body of the test class itself remains completely unchanged.</para>
|
||
|
||
<!-- TODO Consider documenting inheritance for active profiles. -->
|
||
</section>
|
||
|
||
<section xml:id="testcontext-ctx-management-web">
|
||
<title>Loading a WebApplicationContext</title>
|
||
|
||
<para>Spring 3.2 introduces support for loading a
|
||
<interfacename>WebApplicationContext</interfacename> in integration
|
||
tests. To instruct the TestContext framework to load a
|
||
<interfacename>WebApplicationContext</interfacename> instead of a
|
||
standard <interfacename>ApplicationContext</interfacename>, simply
|
||
annotate the respective test class with
|
||
<interfacename>@WebAppConfiguration</interfacename>.</para>
|
||
|
||
<para>The presence of
|
||
<interfacename>@WebAppConfiguration</interfacename> on your test class
|
||
instructs the TestContext framework (TCF) that a
|
||
<interfacename>WebApplicationContext</interfacename> (WAC) should be
|
||
loaded for your integration tests. In the background the TCF makes
|
||
sure that a <interfacename>MockServletContext</interfacename> is
|
||
created and supplied to your test's WAC. By default the base resource
|
||
path for your <interfacename>MockServletContext</interfacename> will
|
||
be set to <emphasis>"src/main/webapp"</emphasis>. This is interpreted
|
||
as a path relative to the root of your JVM (i.e., normally the path to
|
||
your project). If you're familiar with the directory structure of a
|
||
web application in a Maven project, you'll know that
|
||
<emphasis>"src/main/webapp"</emphasis> is the default location for the
|
||
root of your WAR. If you need to override this default, simply provide
|
||
an alternate path to the
|
||
<interfacename>@WebAppConfiguration</interfacename> annotation (e.g.,
|
||
<interfacename>@WebAppConfiguration("src/test/webapp")</interfacename>).
|
||
If you wish to reference a base resource path from the classpath
|
||
instead of the file system, just use Spring's
|
||
<emphasis>classpath:</emphasis> prefix.</para>
|
||
|
||
<para>Please note that Spring's testing support for
|
||
<interfacename>WebApplicationContexts</interfacename> is on par with
|
||
its support for standard
|
||
<interfacename>ApplicationContexts</interfacename>. When testing with
|
||
a <interfacename>WebApplicationContext</interfacename> you are free to
|
||
declare either XML configuration files or
|
||
<interfacename>@Configuration</interfacename> classes via
|
||
<interfacename>@ContextConfiguration</interfacename>. You are of
|
||
course also free to use any other test annotations such as
|
||
<interfacename>@TestExecutionListeners</interfacename>,
|
||
<interfacename>@TransactionConfiguration</interfacename>,
|
||
<interfacename>@ActiveProfiles</interfacename>, etc.</para>
|
||
|
||
<para>The following examples demonstrate some of the various
|
||
configuration options for loading a
|
||
<interfacename>WebApplicationContext</interfacename>.</para>
|
||
|
||
<example>
|
||
<title>Conventions</title>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
|
||
// defaults to "file:src/main/webapp"
|
||
@WebAppConfiguration
|
||
|
||
// detects "WacTests-context.xml" in same package
|
||
// or static nested @Configuration class
|
||
@ContextConfiguration
|
||
|
||
public class WacTests {
|
||
//...
|
||
}</programlisting>
|
||
</example>
|
||
|
||
<para>The above example demonstrates the TestContext framework's
|
||
support for <emphasis>convention over configuration</emphasis>. If you
|
||
annotate a test class with
|
||
<interfacename>@WebAppConfiguration</interfacename> without specifying
|
||
a resource base path, the resource path will effectively default to
|
||
<emphasis>"file:src/main/webapp"</emphasis>. Similarly, if you declare
|
||
<interfacename>@ContextConfiguration</interfacename> without
|
||
specifying resource <interfacename>locations</interfacename>,
|
||
annotated <interfacename>classes</interfacename>, or context
|
||
<interfacename>initializers</interfacename>, Spring will attempt to
|
||
detect the presence of your configuration using conventions (i.e.,
|
||
<emphasis>"WacTests-context.xml"</emphasis> in the same package as the
|
||
<interfacename>WacTests</interfacename> class or static nested
|
||
<interfacename>@Configuration</interfacename> classes).</para>
|
||
|
||
<example>
|
||
<title>Default resource semantics</title>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
|
||
// file system resource
|
||
@WebAppConfiguration("webapp")
|
||
|
||
// classpath resource
|
||
@ContextConfiguration("/spring/test-servlet-config.xml")
|
||
|
||
public class WacTests {
|
||
//...
|
||
}</programlisting>
|
||
</example>
|
||
|
||
<para>This example demonstrates how to explicitly declare a resource
|
||
base path with <interfacename>@WebAppConfiguration</interfacename> and
|
||
an XML resource location with
|
||
<interfacename>@ContextConfiguration</interfacename>. The important
|
||
thing to note here is the different semantics for paths with these two
|
||
annotations. By default,
|
||
<interfacename>@WebAppConfiguration</interfacename> resource paths are
|
||
file system based; whereas,
|
||
<interfacename>@ContextConfiguration</interfacename> resource
|
||
locations are classpath based.</para>
|
||
|
||
<example>
|
||
<title>Explicit resource semantics</title>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
|
||
// classpath resource
|
||
@WebAppConfiguration("classpath:test-web-resources")
|
||
|
||
// file system resource
|
||
@ContextConfiguration("file:src/main/webapp/WEB-INF/servlet-config.xml")
|
||
|
||
public class WacTests {
|
||
//...
|
||
}</programlisting>
|
||
</example>
|
||
|
||
<para>In this third example, we see that we can override the default
|
||
resource semantics for both annotations by specifying a Spring
|
||
resource prefix. Contrast the comments in this example with the
|
||
previous example.</para>
|
||
|
||
<section xml:id="testcontext-ctx-management-web-mocks">
|
||
<title>Working with Web Mocks</title>
|
||
|
||
<para>To provide comprehensive web testing support, Spring 3.2
|
||
introduces a new
|
||
<interfacename>ServletTestExecutionListener</interfacename> that is
|
||
enabled by default. When testing against a
|
||
<interfacename>WebApplicationContext</interfacename> this <link
|
||
linkend="testcontext-key-abstractions">TestExecutionListener</link>
|
||
sets up default thread-local state via Spring Web's
|
||
<interfacename>RequestContextHolder</interfacename> before each test
|
||
method and creates a
|
||
<interfacename>MockHttpServletRequest</interfacename>,
|
||
<interfacename>MockHttpServletResponse</interfacename>, and
|
||
<interfacename>ServletWebRequest</interfacename> based on the base
|
||
resource path configured via
|
||
<interfacename>@WebAppConfiguration</interfacename>.
|
||
<interfacename>ServletTestExecutionListener</interfacename> also
|
||
ensures that the
|
||
<interfacename>MockHttpServletResponse</interfacename> and
|
||
<interfacename>ServletWebRequest</interfacename> can be injected
|
||
into the test instance, and once the test is complete it cleans up
|
||
thread-local state.</para>
|
||
|
||
<para>Once you have a
|
||
<interfacename>WebApplicationContext</interfacename> loaded for your
|
||
test you might find that you need to interact with the web mocks —
|
||
for example, to set up your test fixture or to perform assertions
|
||
after invoking your web component. The following example
|
||
demonstrates which mocks can be autowired into your test instance.
|
||
Note that the <interfacename>WebApplicationContext</interfacename>
|
||
and <interfacename>MockServletContext</interfacename> are both
|
||
cached across the test suite; whereas, the other mocks are managed
|
||
per test method by the
|
||
<interfacename>ServletTestExecutionListener</interfacename>.</para>
|
||
|
||
<example>
|
||
<title>Injecting mocks</title>
|
||
|
||
<programlisting language="java">@WebAppConfiguration
|
||
@ContextConfiguration
|
||
public class WacTests {
|
||
|
||
@Autowired WebApplicationContext wac; // cached
|
||
|
||
@Autowired MockServletContext servletContext; // cached
|
||
|
||
@Autowired MockHttpSession session;
|
||
|
||
@Autowired MockHttpServletRequest request;
|
||
|
||
@Autowired MockHttpServletResponse response;
|
||
|
||
@Autowired ServletWebRequest webRequest;
|
||
|
||
//...
|
||
}</programlisting>
|
||
</example>
|
||
</section>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-ctx-management-caching">
|
||
<title>Context caching</title>
|
||
|
||
<para>Once the TestContext framework loads an
|
||
<interfacename>ApplicationContext</interfacename> (or
|
||
<interfacename>WebApplicationContext</interfacename>) for a test, that
|
||
context will be cached and reused for <emphasis
|
||
role="bold">all</emphasis> subsequent tests that declare the same
|
||
unique context configuration within the same test suite. To understand
|
||
how caching works, it is important to understand what is meant by
|
||
<emphasis>unique</emphasis> and <emphasis>test
|
||
suite</emphasis>.</para>
|
||
|
||
<para>An <interfacename>ApplicationContext</interfacename> can be
|
||
<emphasis>uniquely</emphasis> identified by the combination of
|
||
configuration parameters that are used to load it. Consequently, the
|
||
unique combination of configuration parameters are used to generate a
|
||
<emphasis>key</emphasis> under which the context is cached. The
|
||
TestContext framework uses the following configuration parameters to
|
||
build the context cache key:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><varname>locations</varname> <emphasis>(from
|
||
@ContextConfiguration)</emphasis></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><varname>classes</varname> <emphasis>(from
|
||
@ContextConfiguration)</emphasis></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><varname>contextInitializerClasses</varname> <emphasis>(from
|
||
@ContextConfiguration)</emphasis></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><varname>contextLoader</varname> <emphasis>(from
|
||
@ContextConfiguration)</emphasis></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><varname>activeProfiles</varname> <emphasis>(from
|
||
@ActiveProfiles)</emphasis></para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><varname>resourceBasePath</varname> <emphasis>(from
|
||
@WebAppConfiguration)</emphasis></para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<para>For example, if <classname>TestClassA</classname> specifies
|
||
<literal>{"app-config.xml", "test-config.xml"}</literal> for the
|
||
<varname>locations</varname> (or <varname>value</varname>) attribute
|
||
of <interfacename>@ContextConfiguration</interfacename>, the
|
||
TestContext framework will load the corresponding
|
||
<interfacename>ApplicationContext</interfacename> and store it in a
|
||
<varname>static</varname> context cache under a key that is based
|
||
solely on those locations. So if <classname>TestClassB</classname>
|
||
also defines <literal>{"app-config.xml", "test-config.xml"}</literal>
|
||
for its locations (either explicitly or implicitly through
|
||
inheritance) but does not define
|
||
<interfacename>@WebAppConfiguration</interfacename>, a different
|
||
<interfacename>ContextLoader</interfacename>, different active
|
||
profiles, or different context initializers, then the same
|
||
<interfacename>ApplicationContext</interfacename> will be shared by
|
||
both test classes. This means that the setup cost for loading an
|
||
application context is incurred only once (per test suite), and
|
||
subsequent test execution is much faster.</para>
|
||
|
||
<note>
|
||
<title>Test suites and forked processes</title>
|
||
|
||
<para>The Spring TestContext framework stores application contexts
|
||
in a <emphasis>static</emphasis> cache. This means that the context
|
||
is literally stored in a <varname>static</varname> variable. In
|
||
other words, if tests execute in separate processes the static cache
|
||
will be cleared between each test execution, and this will
|
||
effectively disable the caching mechanism.</para>
|
||
|
||
<para>To benefit from the caching mechanism, all tests must run
|
||
within the same process or test suite. This can be achieved by
|
||
executing all tests as a group within an IDE. Similarly, when
|
||
executing tests with a build framework such as Ant, Maven, or Gradle
|
||
it is important to make sure that the build framework does not
|
||
<emphasis>fork</emphasis> between tests. For example, if the <link
|
||
xl:href="http://maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html#forkMode">forkMode</link>
|
||
for the Maven Surefire plug-in is set to <literal>always</literal>
|
||
or <literal>pertest</literal>, the TestContext framework will not be
|
||
able to cache application contexts between test classes and the
|
||
build process will run significantly slower as a result.</para>
|
||
</note>
|
||
|
||
<para>In the unlikely case that a test corrupts the application
|
||
context and requires reloading — for example, by modifying a bean
|
||
definition or the state of an application object — you can annotate
|
||
your test class or test method with
|
||
<interfacename>@DirtiesContext</interfacename> (see the discussion of
|
||
<interfacename>@DirtiesContext</interfacename> in <xref
|
||
linkend="integration-testing-annotations-spring"/>). This instructs
|
||
Spring to remove the context from the cache and rebuild the
|
||
application context before executing the next test. Note that support
|
||
for the <interfacename>@DirtiesContext</interfacename> annotation is
|
||
provided by the
|
||
<classname>DirtiesContextTestExecutionListener</classname> which is
|
||
enabled by default.</para>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-ctx-management-ctx-hierarchies">
|
||
<title>Context hierarchies</title>
|
||
|
||
<para>When writing integration tests that rely on a loaded Spring
|
||
<interfacename>ApplicationContext</interfacename>, it is often
|
||
sufficient to test against a single context; however, there are times
|
||
when it is beneficial or even necessary to test against a hierarchy of
|
||
<interfacename>ApplicationContext</interfacename>s. For example, if
|
||
you are developing a Spring MVC web application you will typically
|
||
have a root <interfacename>WebApplicationContext</interfacename>
|
||
loaded via Spring's <classname>ContextLoaderListener</classname> and a
|
||
child <interfacename>WebApplicationContext</interfacename> loaded via
|
||
Spring's <classname>DispatcherServlet</classname>. This results in a
|
||
parent-child context hierarchy where shared components and
|
||
infrastructure configuration are declared in the root context and
|
||
consumed in the child context by web-specific components. Another use
|
||
case can be found in Spring Batch applications where you often have a
|
||
parent context that provides configuration for shared batch
|
||
infrastructure and a child context for the configuration of a specific
|
||
batch job.</para>
|
||
|
||
<para>As of Spring Framework 3.2.2, it is possible to write
|
||
integration tests that use context hierarchies by declaring context
|
||
configuration via the <interfacename>@ContextHierarchy</interfacename>
|
||
annotation, either on an individual test class or within a test class
|
||
hierarchy. If a context hierarchy is declared on multiple classes
|
||
within a test class hierarchy it is also possible to merge or override
|
||
the context configuration for a specific, named level in the context
|
||
hierarchy. When merging configuration for a given level in the
|
||
hierarchy the configuration resource type (i.e., XML configuration
|
||
files or annotated classes) must be consistent; otherwise, it is
|
||
perfectly acceptable to have different levels in a context hierarchy
|
||
configured using different resource types.</para>
|
||
|
||
<para>The following JUnit-based examples demonstrate common
|
||
configuration scenarios for integration tests that require the use of
|
||
context hierarchies.</para>
|
||
|
||
<example>
|
||
<title>Single test class with context hierarchy</title>
|
||
|
||
<para><classname>ControllerIntegrationTests</classname> represents a
|
||
typical integration testing scenario for a Spring MVC web
|
||
application by declaring a context hierarchy consisting of two
|
||
levels, one for the <emphasis>root</emphasis> WebApplicationContext
|
||
(loaded using the <classname>TestAppConfig</classname>
|
||
<interfacename>@Configuration</interfacename> class) and one for the
|
||
<emphasis>dispatcher servlet</emphasis>
|
||
<interfacename>WebApplicationContext</interfacename> (loaded using
|
||
the <classname>WebConfig</classname>
|
||
<interfacename>@Configuration</interfacename> class). The
|
||
<interfacename>WebApplicationContext</interfacename> that is
|
||
<emphasis>autowired</emphasis> into the test instance is the one for
|
||
the child context (i.e., the lowest context in the
|
||
hierarchy).</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
@WebAppConfiguration
|
||
@ContextHierarchy({
|
||
@ContextConfiguration(classes = TestAppConfig.class),
|
||
@ContextConfiguration(classes = WebConfig.class)
|
||
})
|
||
public class ControllerIntegrationTests {
|
||
|
||
@Autowired
|
||
private WebApplicationContext wac;
|
||
|
||
// ...
|
||
}</programlisting>
|
||
</example>
|
||
|
||
<example>
|
||
<title>Class hierarchy with implicit parent context</title>
|
||
|
||
<para>The following test classes define a context hierarchy within a
|
||
test class hierarchy. <classname>AbstractWebTests</classname>
|
||
declares the configuration for a root
|
||
<interfacename>WebApplicationContext</interfacename> in a
|
||
Spring-powered web application. Note, however, that
|
||
<classname>AbstractWebTests</classname> does not declare
|
||
<interfacename>@ContextHierarchy</interfacename>; consequently,
|
||
subclasses of <classname>AbstractWebTests</classname> can optionally
|
||
participate in a context hierarchy or simply follow the standard
|
||
semantics for <interfacename>@ContextConfiguration</interfacename>.
|
||
<classname>SoapWebServiceTests</classname> and
|
||
<classname>RestWebServiceTests</classname> both extend
|
||
<classname>AbstractWebTests</classname> and define a context
|
||
hierarchy via <interfacename>@ContextHierarchy</interfacename>. The
|
||
result is that three application contexts will be loaded (one for
|
||
each declaration of
|
||
<interfacename>@ContextConfiguration</interfacename>), and the
|
||
application context loaded based on the configuration in
|
||
<classname>AbstractWebTests</classname> will be set as the parent
|
||
context for each of the contexts loaded for the concrete
|
||
subclasses.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
@WebAppConfiguration
|
||
@ContextConfiguration("file:src/main/webapp/WEB-INF/applicationContext.xml")
|
||
public abstract class AbstractWebTests {}
|
||
|
||
@ContextHierarchy(@ContextConfiguration("/spring/soap-ws-config.xml")
|
||
public class SoapWebServiceTests extends AbstractWebTests {}
|
||
|
||
@ContextHierarchy(@ContextConfiguration("/spring/rest-ws-config.xml")
|
||
public class RestWebServiceTests extends AbstractWebTests {}</programlisting>
|
||
</example>
|
||
|
||
<example>
|
||
<title>Class hierarchy with merged context hierarchy
|
||
configuration</title>
|
||
|
||
<para>The following classes demonstrate the use of
|
||
<emphasis>named</emphasis> hierarchy levels in order to
|
||
<emphasis>merge</emphasis> the configuration for specific levels in
|
||
a context hierarchy. <classname>BaseTests</classname> defines two
|
||
levels in the hierarchy, <literal>parent</literal> and
|
||
<literal>child</literal>. <classname>ExtendedTests</classname>
|
||
extends <classname>BaseTests</classname> and instructs the Spring
|
||
TestContext Framework to merge the context configuration for the
|
||
<literal>child</literal> hierarchy level, simply by ensuring that
|
||
the names declared via
|
||
<interfacename>ContextConfiguration</interfacename>'s
|
||
<varname>name</varname> attribute are both
|
||
<literal>"child"</literal>. The result is that three application
|
||
contexts will be loaded: one for
|
||
<literal>"/app-config.xml"</literal>, one for
|
||
<literal>"/user-config.xml"</literal>, and one for
|
||
<literal>{"/user-config.xml", "/order-config.xml"}</literal>. As
|
||
with the previous example, the application context loaded from
|
||
<literal>"/app-config.xml"</literal> will be set as the parent
|
||
context for the contexts loaded from
|
||
<literal>"/user-config.xml"</literal> and
|
||
<literal>{"/user-config.xml", "/order-config.xml"}</literal>.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
@ContextHierarchy({
|
||
@ContextConfiguration(name = "parent", locations = "/app-config.xml"),
|
||
@ContextConfiguration(name = "child", locations = "/user-config.xml")
|
||
})
|
||
public class BaseTests {}
|
||
|
||
@ContextHierarchy(
|
||
@ContextConfiguration(name = "child", locations = "/order-config.xml")
|
||
)
|
||
public class ExtendedTests extends BaseTests {}</programlisting>
|
||
</example>
|
||
|
||
<example>
|
||
<title>Class hierarchy with overridden context hierarchy
|
||
configuration</title>
|
||
|
||
<para>In contrast to the previous example, this example demonstrates
|
||
how to <emphasis>override</emphasis> the configuration for a given
|
||
named level in a context hierarchy by setting
|
||
<interfacename>ContextConfiguration</interfacename>'s
|
||
<varname>inheritLocations</varname> flag to
|
||
<literal>false</literal>. Consequently, the application context for
|
||
<classname>ExtendedTests</classname> will be loaded only from
|
||
<literal>"/test-user-config.xml"</literal> and will have its parent
|
||
set to the context loaded from
|
||
<literal>"/app-config.xml"</literal>.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
@ContextHierarchy({
|
||
@ContextConfiguration(name = "parent", locations = "/app-config.xml"),
|
||
@ContextConfiguration(name = "child", locations = "/user-config.xml")
|
||
})
|
||
public class BaseTests {}
|
||
|
||
@ContextHierarchy(
|
||
@ContextConfiguration(
|
||
name = "child",
|
||
locations = "/test-user-config.xml",
|
||
inheritLocations = false
|
||
))
|
||
public class ExtendedTests extends BaseTests {}</programlisting>
|
||
</example>
|
||
|
||
<note>
|
||
<title>Dirtying a context within a context hierarchy</title>
|
||
|
||
<para>If <interfacename>@DirtiesContext</interfacename> is used in a
|
||
test whose context is configured as part of a context hierarchy, the
|
||
<varname>hierarchyMode</varname> flag can be used to control how the
|
||
context cache is cleared. For further details consult the discussion
|
||
of <interfacename>@DirtiesContext</interfacename> in <xref
|
||
linkend="integration-testing-annotations-spring"/> and the Javadoc
|
||
for <interfacename>@DirtiesContext</interfacename>.</para>
|
||
</note>
|
||
</section>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-fixture-di">
|
||
<title>Dependency injection of test fixtures</title>
|
||
|
||
<para>When you use the
|
||
<classname>DependencyInjectionTestExecutionListener</classname> — which
|
||
is configured by default — the dependencies of your test instances are
|
||
<emphasis>injected</emphasis> from beans in the application context that
|
||
you configured with
|
||
<interfacename>@ContextConfiguration</interfacename>. You may use setter
|
||
injection, field injection, or both, depending on which annotations you
|
||
choose and whether you place them on setter methods or fields. For
|
||
consistency with the annotation support introduced in Spring 2.5 and
|
||
3.0, you can use Spring's <interfacename>@Autowired</interfacename>
|
||
annotation or the <interfacename>@Inject</interfacename> annotation from
|
||
JSR 300.</para>
|
||
|
||
<tip>
|
||
<para>The TestContext framework does not instrument the manner in
|
||
which a test instance is instantiated. Thus the use of
|
||
<interfacename>@Autowired</interfacename> or
|
||
<interfacename>@Inject</interfacename> for constructors has no effect
|
||
for test classes.</para>
|
||
</tip>
|
||
|
||
<para>Because <interfacename>@Autowired</interfacename> is used to
|
||
perform <link linkend="beans-factory-autowire"> <emphasis>autowiring by
|
||
type</emphasis> </link>, if you have multiple bean definitions of the
|
||
same type, you cannot rely on this approach for those particular beans.
|
||
In that case, you can use <interfacename>@Autowired</interfacename> in
|
||
conjunction with <interfacename>@Qualifier</interfacename>. As of Spring
|
||
3.0 you may also choose to use <interfacename>@Inject</interfacename> in
|
||
conjunction with <interfacename>@Named</interfacename>. Alternatively,
|
||
if your test class has access to its
|
||
<classname>ApplicationContext</classname>, you can perform an explicit
|
||
lookup by using (for example) a call to
|
||
<methodname>applicationContext.getBean("titleRepository")</methodname>.</para>
|
||
|
||
<para>If you do not want dependency injection applied to your test
|
||
instances, simply do not annotate fields or setter methods with
|
||
<interfacename>@Autowired</interfacename> or
|
||
<interfacename>@Inject</interfacename>. Alternatively, you can disable
|
||
dependency injection altogether by explicitly configuring your class
|
||
with <interfacename>@TestExecutionListeners</interfacename> and omitting
|
||
<literal>DependencyInjectionTestExecutionListener.class</literal> from
|
||
the list of listeners.</para>
|
||
|
||
<para>Consider the scenario of testing a
|
||
<classname>HibernateTitleRepository</classname> class, as outlined in
|
||
the <link linkend="integration-testing-goals">Goals</link> section. The
|
||
next two code listings demonstrate the use of
|
||
<interfacename>@Autowired</interfacename> on fields and setter methods.
|
||
The application context configuration is presented after all sample code
|
||
listings.</para>
|
||
|
||
<note>
|
||
<para>The dependency injection behavior in the following code listings
|
||
is not specific to JUnit. The same DI techniques can be used in
|
||
conjunction with any testing framework.</para>
|
||
|
||
<para>The following examples make calls to static assertion methods
|
||
such as <literal>assertNotNull()</literal> but without prepending the
|
||
call with <literal>Assert</literal>. In such cases, assume that the
|
||
method was properly imported through an <literal>import
|
||
static</literal> declaration that is not shown in the example.</para>
|
||
</note>
|
||
|
||
<para>The first code listing shows a JUnit-based implementation of the
|
||
test class that uses <interfacename>@Autowired</interfacename> for field
|
||
injection.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
<lineannotation>// specifies the Spring configuration to load for this test fixture</lineannotation>
|
||
<emphasis role="bold">@ContextConfiguration("repository-config.xml")</emphasis>
|
||
public class HibernateTitleRepositoryTests {
|
||
|
||
<lineannotation>// this instance will be dependency injected by type</lineannotation>
|
||
<emphasis role="bold">@Autowired</emphasis>
|
||
private HibernateTitleRepository titleRepository;
|
||
|
||
@Test
|
||
public void findById() {
|
||
Title title = titleRepository.findById(new Long(10));
|
||
assertNotNull(title);
|
||
}
|
||
}</programlisting>
|
||
|
||
<para>Alternatively, you can configure the class to use
|
||
<interfacename>@Autowired</interfacename> for setter injection as seen
|
||
below.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
<lineannotation>// specifies the Spring configuration to load for this test fixture</lineannotation>
|
||
<emphasis role="bold">@ContextConfiguration("repository-config.xml")</emphasis>
|
||
public class HibernateTitleRepositoryTests {
|
||
|
||
<lineannotation>// this instance will be dependency injected by type</lineannotation>
|
||
private HibernateTitleRepository titleRepository;
|
||
|
||
<emphasis role="bold">@Autowired</emphasis>
|
||
public void setTitleRepository(HibernateTitleRepository titleRepository) {
|
||
this.titleRepository = titleRepository;
|
||
}
|
||
|
||
@Test
|
||
public void findById() {
|
||
Title title = titleRepository.findById(new Long(10));
|
||
assertNotNull(title);
|
||
}
|
||
}</programlisting>
|
||
|
||
<para>The preceding code listings use the same XML context file
|
||
referenced by the <interfacename>@ContextConfiguration</interfacename>
|
||
annotation (that is, <literal>repository-config.xml</literal>), which
|
||
looks like this:</para>
|
||
|
||
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?>
|
||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||
http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||
|
||
<lineannotation><!-- this bean will be injected into the HibernateTitleRepositoryTests class --></lineannotation>
|
||
<bean id="<emphasis role="bold">titleRepository</emphasis>" class="<emphasis
|
||
role="bold">com.foo.repository.hibernate.HibernateTitleRepository</emphasis>">
|
||
<property name="sessionFactory" ref="sessionFactory"/>
|
||
</bean>
|
||
|
||
<bean id="sessionFactory"
|
||
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
|
||
<lineannotation><!-- configuration elided for brevity --></lineannotation>
|
||
</bean>
|
||
|
||
</beans></programlisting>
|
||
|
||
<note>
|
||
<para>If you are extending from a Spring-provided test base class that
|
||
happens to use <interfacename>@Autowired</interfacename> on one of its
|
||
setter methods, you might have multiple beans of the affected type
|
||
defined in your application context: for example, multiple
|
||
<interfacename>DataSource</interfacename> beans. In such a case, you
|
||
can override the setter method and use the
|
||
<interfacename>@Qualifier</interfacename> annotation to indicate a
|
||
specific target bean as follows, but make sure to delegate to the
|
||
overridden method in the superclass as well.</para>
|
||
|
||
<programlisting language="java"><lineannotation>// ...</lineannotation>
|
||
|
||
@Autowired
|
||
@Override
|
||
public void setDataSource(<emphasis role="bold">@Qualifier("myDataSource")</emphasis> DataSource dataSource) {
|
||
<emphasis role="bold">super</emphasis>.setDataSource(dataSource);
|
||
}
|
||
|
||
<lineannotation>// ...</lineannotation></programlisting>
|
||
|
||
<para>The specified qualifier value indicates the specific
|
||
<interfacename>DataSource</interfacename> bean to inject, narrowing
|
||
the set of type matches to a specific bean. Its value is matched
|
||
against <literal><qualifier></literal> declarations within the
|
||
corresponding <literal><bean></literal> definitions. The bean
|
||
name is used as a fallback qualifier value, so you may effectively
|
||
also point to a specific bean by name there (as shown above, assuming
|
||
that "myDataSource" is the bean id).</para>
|
||
</note>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-web-scoped-beans">
|
||
<title>Testing request and session scoped beans</title>
|
||
|
||
<para><link linkend="beans-factory-scopes-other">Request and session
|
||
scoped beans</link> have been supported by Spring for several years now,
|
||
but it's always been a bit non-trivial to test them. As of Spring 3.2
|
||
it's now a breeze to test your request-scoped and session-scoped beans
|
||
by following these steps.</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>Ensure that a
|
||
<interfacename>WebApplicationContext</interfacename> is loaded for
|
||
your test by annotating your test class with
|
||
<interfacename>@WebAppConfiguration</interfacename>.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>Inject the mock request or session into your test instance and
|
||
prepare your test fixture as appropriate.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>Invoke your web component that you retrieved from the
|
||
configured <interfacename>WebApplicationContext</interfacename>
|
||
(i.e., via dependency injection).</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>Perform assertions against the mocks.</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<para>The following code snippet displays the XML configuration for a
|
||
login use case. Note that the <literal>userService</literal> bean has a
|
||
dependency on a request-scoped <literal>loginAction</literal> bean.
|
||
Also, the <classname>LoginAction</classname> is instantiated using <link
|
||
linkend="expressions">SpEL expressions</link> that retrieve the username
|
||
and password from the current HTTP request. In our test, we will want to
|
||
configure these request parameters via the mock managed by the
|
||
TestContext framework.</para>
|
||
|
||
<example>
|
||
<title>Request-scoped bean configuration</title>
|
||
|
||
<programlisting language="xml"><beans>
|
||
|
||
<bean id="userService"
|
||
class="com.example.SimpleUserService"
|
||
c:loginAction-ref="loginAction" />
|
||
|
||
<bean id="loginAction" class="com.example.LoginAction"
|
||
c:username="#{request.getParameter('user')}"
|
||
c:password="#{request.getParameter('pswd')}"
|
||
scope="request">
|
||
<aop:scoped-proxy />
|
||
</bean>
|
||
|
||
</beans></programlisting>
|
||
</example>
|
||
|
||
<para>In <classname>RequestScopedBeanTests</classname> we inject both
|
||
the <classname>UserService</classname> (i.e., the subject under test)
|
||
and the <classname>MockHttpServletRequest</classname> into our test
|
||
instance. Within our <function>requestScope()</function> test method we
|
||
set up our test fixture by setting request parameters in the provided
|
||
<classname>MockHttpServletRequest</classname>. When the
|
||
<function>loginUser()</function> method is invoked on our
|
||
<literal>userService</literal> we are assured that the user service has
|
||
access to the request-scoped <literal>loginAction</literal> for the
|
||
current <classname>MockHttpServletRequest</classname> (i.e., the one we
|
||
just set parameters in). We can then perform assertions against the
|
||
results based on the known inputs for the username and password.</para>
|
||
|
||
<example>
|
||
<title>Request-scoped bean test</title>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
@ContextConfiguration
|
||
@WebAppConfiguration
|
||
public class RequestScopedBeanTests {
|
||
|
||
@Autowired UserService userService;
|
||
@Autowired MockHttpServletRequest request;
|
||
|
||
@Test
|
||
public void requestScope() {
|
||
|
||
request.setParameter("user", "enigma");
|
||
request.setParameter("pswd", "$pr!ng");
|
||
|
||
LoginResults results = userService.loginUser();
|
||
|
||
// assert results
|
||
}
|
||
}</programlisting>
|
||
</example>
|
||
|
||
<para>The following code snippet is similar to the one we saw above for
|
||
a request-scoped bean; however, this time the
|
||
<literal>userService</literal> bean has a dependency on a session-scoped
|
||
<literal>userPreferences</literal> bean. Note that the
|
||
<classname>UserPreferences</classname> bean is instantiated using a SpEL
|
||
expression that retrieves the <emphasis>theme</emphasis> from the
|
||
current HTTP session. In our test, we will need to configure a theme in
|
||
the mock session managed by the TestContext framework.</para>
|
||
|
||
<example>
|
||
<title>Session-scoped bean configuration</title>
|
||
|
||
<programlisting language="xml"><beans>
|
||
|
||
<bean id="userService"
|
||
class="com.example.SimpleUserService"
|
||
c:userPreferences-ref="userPreferences" />
|
||
|
||
<bean id="userPreferences"
|
||
class="com.example.UserPreferences"
|
||
c:theme="#{session.getAttribute('theme')}"
|
||
scope="session">
|
||
<aop:scoped-proxy />
|
||
</bean>
|
||
|
||
</beans></programlisting>
|
||
</example>
|
||
|
||
<para>In <classname>SessionScopedBeanTests</classname> we inject the
|
||
<classname>UserService</classname> and the
|
||
<classname>MockHttpSession</classname> into our test instance. Within
|
||
our <function>sessionScope()</function> test method we set up our test
|
||
fixture by setting the expected "theme" attribute in the provided
|
||
<classname>MockHttpSession</classname>. When the
|
||
<function>processUserPreferences()</function> method is invoked on our
|
||
<literal>userService</literal> we are assured that the user service has
|
||
access to the session-scoped <literal>userPreferences</literal> for the
|
||
current <classname>MockHttpSession</classname>, and we can perform
|
||
assertions against the results based on the configured theme.</para>
|
||
|
||
<example>
|
||
<title>Session-scoped bean test</title>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
@ContextConfiguration
|
||
@WebAppConfiguration
|
||
public class SessionScopedBeanTests {
|
||
|
||
@Autowired UserService userService;
|
||
@Autowired MockHttpSession session;
|
||
|
||
@Test
|
||
public void sessionScope() throws Exception {
|
||
|
||
session.setAttribute("theme", "blue");
|
||
|
||
Results results = userService.processUserPreferences();
|
||
|
||
// assert results
|
||
}
|
||
}</programlisting>
|
||
</example>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-tx">
|
||
<title>Transaction management</title>
|
||
|
||
<para>In the TestContext framework, transactions are managed by the
|
||
<classname>TransactionalTestExecutionListener</classname>. Note that
|
||
<classname>TransactionalTestExecutionListener</classname> is configured
|
||
by default, even if you do not explicitly declare
|
||
<interfacename>@TestExecutionListeners</interfacename> on your test
|
||
class. To enable support for transactions, however, you must provide a
|
||
<classname>PlatformTransactionManager</classname> bean in the
|
||
application context loaded by
|
||
<interfacename>@ContextConfiguration</interfacename> semantics. In
|
||
addition, you must declare <interfacename>@Transactional</interfacename>
|
||
either at the class or method level for your tests.</para>
|
||
|
||
<para>For class-level transaction configuration (i.e., setting an
|
||
explicit bean name for the transaction manager and the default rollback
|
||
flag), see the <interfacename>@TransactionConfiguration</interfacename>
|
||
entry in the <link linkend="integration-testing-annotations">annotation
|
||
support</link> section.</para>
|
||
|
||
<para>If transactions are not enabled for the entire test class, you can
|
||
annotate methods explicitly with
|
||
<interfacename>@Transactional</interfacename>. To control whether a
|
||
transaction should commit for a particular test method, you can use the
|
||
<interfacename>@Rollback</interfacename> annotation to override the
|
||
class-level default rollback setting.</para>
|
||
|
||
<para><emphasis><link linkend="testcontext-support-classes-junit4">
|
||
<classname>AbstractTransactionalJUnit4SpringContextTests</classname>
|
||
</link> and <link linkend="testcontext-support-classes-testng">
|
||
<classname>AbstractTransactionalTestNGSpringContextTests</classname>
|
||
</link> are preconfigured for transactional support at the class
|
||
level.</emphasis></para>
|
||
|
||
<para>Occasionally you need to execute certain code before or after a
|
||
transactional test method but outside the transactional context, for
|
||
example, to verify the initial database state prior to execution of your
|
||
test or to verify expected transactional commit behavior after test
|
||
execution (if the test was configured not to roll back the transaction).
|
||
<classname>TransactionalTestExecutionListener</classname> supports the
|
||
<interfacename>@BeforeTransaction</interfacename> and
|
||
<interfacename>@AfterTransaction</interfacename> annotations exactly for
|
||
such scenarios. Simply annotate any <literal>public void</literal>
|
||
method in your test class with one of these annotations, and the
|
||
<classname>TransactionalTestExecutionListener</classname> ensures that
|
||
your <emphasis>before transaction method</emphasis> or <emphasis>after
|
||
transaction method</emphasis> is executed at the appropriate
|
||
time.</para>
|
||
|
||
<tip>
|
||
<para>Any <emphasis>before methods</emphasis> (such as methods
|
||
annotated with JUnit's <interfacename>@Before</interfacename>) and any
|
||
<emphasis>after methods</emphasis> (such as methods annotated with
|
||
JUnit's <interfacename>@After</interfacename>) are executed <emphasis
|
||
role="bold">within</emphasis> a transaction. In addition, methods
|
||
annotated with <interfacename>@BeforeTransaction</interfacename> or
|
||
<interfacename>@AfterTransaction</interfacename> are naturally not
|
||
executed for tests annotated with
|
||
<interfacename>@NotTransactional</interfacename>. However,
|
||
<interfacename>@NotTransactional</interfacename> is deprecated as of
|
||
Spring 3.0.</para>
|
||
</tip>
|
||
|
||
<para>The following JUnit-based example displays a fictitious
|
||
integration testing scenario highlighting several transaction-related
|
||
annotations. Consult the <link
|
||
linkend="integration-testing-annotations">annotation support</link>
|
||
section for further information and configuration examples.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
@ContextConfiguration
|
||
<emphasis role="bold">@TransactionConfiguration(transactionManager="txMgr", defaultRollback=false)</emphasis>
|
||
<emphasis role="bold">@Transactional</emphasis>
|
||
public class FictitiousTransactionalTest {
|
||
|
||
<emphasis role="bold">@BeforeTransaction</emphasis>
|
||
public void verifyInitialDatabaseState() {
|
||
<lineannotation>// logic to verify the initial state before a transaction is started</lineannotation>
|
||
}
|
||
|
||
@Before
|
||
public void setUpTestDataWithinTransaction() {
|
||
<lineannotation>// set up test data within the transaction</lineannotation>
|
||
}
|
||
|
||
@Test
|
||
<lineannotation>// overrides the class-level defaultRollback setting</lineannotation>
|
||
<emphasis role="bold">@Rollback(true)</emphasis>
|
||
public void modifyDatabaseWithinTransaction() {
|
||
<lineannotation>// logic which uses the test data and modifies database state</lineannotation>
|
||
}
|
||
|
||
@After
|
||
public void tearDownWithinTransaction() {
|
||
<lineannotation>// execute "tear down" logic within the transaction</lineannotation>
|
||
}
|
||
|
||
<emphasis role="bold">@AfterTransaction</emphasis>
|
||
public void verifyFinalDatabaseState() {
|
||
<lineannotation>// logic to verify the final state after transaction has rolled back</lineannotation>
|
||
}
|
||
|
||
}</programlisting>
|
||
|
||
<anchor xml:id="testcontext-tx-false-positives"/>
|
||
|
||
<note>
|
||
<title>Avoid false positives when testing ORM code</title>
|
||
|
||
<para>When you test application code that manipulates the state of the
|
||
Hibernate session, make sure to <emphasis>flush</emphasis> the
|
||
underlying session within test methods that execute that code. Failing
|
||
to flush the underlying session can produce <emphasis>false
|
||
positives</emphasis>: your test may pass, but the same code throws an
|
||
exception in a live, production environment. In the following
|
||
Hibernate-based example test case, one method demonstrates a false
|
||
positive, and the other method correctly exposes the results of
|
||
flushing the session. Note that this applies to JPA and any other ORM
|
||
frameworks that maintain an in-memory <emphasis>unit of
|
||
work</emphasis>.</para>
|
||
|
||
<programlisting language="java"><lineannotation>// ...</lineannotation>
|
||
|
||
@Autowired
|
||
private SessionFactory sessionFactory;
|
||
|
||
@Test // no expected exception!
|
||
public void falsePositive() {
|
||
updateEntityInHibernateSession();
|
||
// False positive: an exception will be thrown once the session is
|
||
// finally flushed (i.e., in production code)
|
||
}
|
||
|
||
@Test(expected = GenericJDBCException.class)
|
||
public void updateWithSessionFlush() {
|
||
updateEntityInHibernateSession();
|
||
// Manual flush is required to avoid false positive in test
|
||
sessionFactory.getCurrentSession().flush();
|
||
}
|
||
|
||
<lineannotation>// ...</lineannotation></programlisting>
|
||
</note>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-support-classes">
|
||
<title>TestContext Framework support classes</title>
|
||
|
||
<section xml:id="testcontext-support-classes-junit4">
|
||
<title>JUnit support classes</title>
|
||
|
||
<para>The <literal>org.springframework.test.context.junit4</literal>
|
||
package provides support classes for JUnit 4.5+ based test
|
||
cases.</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><classname>AbstractJUnit4SpringContextTests</classname>:
|
||
Abstract base test class that integrates the <emphasis>Spring
|
||
TestContext Framework</emphasis> with explicit
|
||
<classname>ApplicationContext</classname> testing support in a
|
||
JUnit 4.5+ environment.</para>
|
||
|
||
<para>When you extend
|
||
<classname>AbstractJUnit4SpringContextTests</classname>, you can
|
||
access the following <literal>protected</literal> instance
|
||
variable:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><literal>applicationContext</literal>: Use this variable
|
||
to perform explicit bean lookups or to test the state of the
|
||
context as a whole.</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><classname>AbstractTransactionalJUnit4SpringContextTests</classname>:
|
||
Abstract <emphasis>transactional</emphasis> extension of
|
||
<classname>AbstractJUnit4SpringContextTests</classname> that also
|
||
adds some convenience functionality for JDBC access. Expects a
|
||
<classname>javax.sql.DataSource</classname> bean and a
|
||
<interfacename>PlatformTransactionManager</interfacename> bean to
|
||
be defined in the <classname>ApplicationContext</classname>. When
|
||
you extend
|
||
<classname>AbstractTransactionalJUnit4SpringContextTests</classname>
|
||
you can access the following <literal>protected</literal> instance
|
||
variables:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><literal>applicationContext</literal>: Inherited from
|
||
the <classname>AbstractJUnit4SpringContextTests</classname>
|
||
superclass. Use this variable to perform explicit bean lookups
|
||
or to test the state of the context as a whole.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><literal>jdbcTemplate</literal>: Use this variable to
|
||
execute SQL statements to query the database. Such queries can
|
||
be used to confirm database state both <emphasis>prior
|
||
to</emphasis> and <emphasis>after</emphasis> execution of
|
||
database-related application code, and Spring ensures that
|
||
such queries run in the scope of the same transaction as the
|
||
application code. When used in conjunction with an ORM tool,
|
||
be sure to avoid <link
|
||
linkend="testcontext-tx-false-positives">false
|
||
positives</link>.</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<tip>
|
||
<para>These classes are a convenience for extension. If you do not
|
||
want your test classes to be tied to a Spring-specific class
|
||
hierarchy — for example, if you want to directly extend the class
|
||
you are testing — you can configure your own custom test classes by
|
||
using
|
||
<interfacename>@RunWith(SpringJUnit4ClassRunner.class)</interfacename>,
|
||
<interfacename>@ContextConfiguration</interfacename>,
|
||
<interfacename>@TestExecutionListeners</interfacename>, and so
|
||
on.</para>
|
||
</tip>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-junit4-runner">
|
||
<title>Spring JUnit Runner</title>
|
||
|
||
<para>The <emphasis>Spring TestContext Framework</emphasis> offers
|
||
full integration with JUnit 4.5+ through a custom runner (tested on
|
||
JUnit 4.5 – 4.10). By annotating test classes with
|
||
<literal>@RunWith(SpringJUnit4ClassRunner.class)</literal>, developers
|
||
can implement standard JUnit-based unit and integration tests and
|
||
simultaneously reap the benefits of the TestContext framework such as
|
||
support for loading application contexts, dependency injection of test
|
||
instances, transactional test method execution, and so on. The
|
||
following code listing displays the minimal requirements for
|
||
configuring a test class to run with the custom Spring Runner.
|
||
<interfacename>@TestExecutionListeners</interfacename> is configured
|
||
with an empty list in order to disable the default listeners, which
|
||
otherwise would require an ApplicationContext to be configured through
|
||
<interfacename>@ContextConfiguration</interfacename>.</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
@TestExecutionListeners({})
|
||
public class SimpleTest {
|
||
|
||
@Test
|
||
public void testMethod() {
|
||
<lineannotation>// execute test logic...</lineannotation>
|
||
}
|
||
}</programlisting>
|
||
</section>
|
||
|
||
<section xml:id="testcontext-support-classes-testng">
|
||
<title>TestNG support classes</title>
|
||
|
||
<para>The <literal>org.springframework.test.context.testng</literal>
|
||
package provides support classes for TestNG based test cases.</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><classname>AbstractTestNGSpringContextTests</classname>:
|
||
Abstract base test class that integrates the <emphasis>Spring
|
||
TestContext Framework</emphasis> with explicit
|
||
<classname>ApplicationContext</classname> testing support in a
|
||
TestNG environment.</para>
|
||
|
||
<para>When you extend
|
||
<classname>AbstractTestNGSpringContextTests</classname>, you can
|
||
access the following <literal>protected</literal> instance
|
||
variable:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><literal>applicationContext</literal>: Use this variable
|
||
to perform explicit bean lookups or to test the state of the
|
||
context as a whole.</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><classname>AbstractTransactionalTestNGSpringContextTests</classname>:
|
||
Abstract <emphasis>transactional</emphasis> extension of
|
||
<classname>AbstractTestNGSpringContextTests</classname> that adds
|
||
some convenience functionality for JDBC access. Expects a
|
||
<classname>javax.sql.DataSource</classname> bean and a
|
||
<interfacename>PlatformTransactionManager</interfacename> bean to
|
||
be defined in the <classname>ApplicationContext</classname>. When
|
||
you extend
|
||
<classname>AbstractTransactionalTestNGSpringContextTests</classname>,
|
||
you can access the following <literal>protected</literal> instance
|
||
variables:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><literal>applicationContext</literal>: Inherited from
|
||
the <classname>AbstractTestNGSpringContextTests</classname>
|
||
superclass. Use this variable to perform explicit bean lookups
|
||
or to test the state of the context as a whole.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><literal>jdbcTemplate</literal>: Use this variable to
|
||
execute SQL statements to query the database. Such queries can
|
||
be used to confirm database state both <emphasis>prior
|
||
to</emphasis> and <emphasis>after</emphasis> execution of
|
||
database-related application code, and Spring ensures that
|
||
such queries run in the scope of the same transaction as the
|
||
application code. When used in conjunction with an ORM tool,
|
||
be sure to avoid <link
|
||
linkend="testcontext-tx-false-positives">false
|
||
positives</link>.</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<tip>
|
||
<para>These classes are a convenience for extension. If you do not
|
||
want your test classes to be tied to a Spring-specific class
|
||
hierarchy — for example, if you want to directly extend the class
|
||
you are testing — you can configure your own custom test classes by
|
||
using <interfacename>@ContextConfiguration</interfacename>,
|
||
<interfacename>@TestExecutionListeners</interfacename>, and so on,
|
||
and by manually instrumenting your test class with a
|
||
<classname>TestContextManager</classname>. See the source code of
|
||
<classname>AbstractTestNGSpringContextTests</classname> for an
|
||
example of how to instrument your test class.</para>
|
||
</tip>
|
||
</section>
|
||
</section>
|
||
</section>
|
||
|
||
<section xml:id="spring-mvc-test-framework">
|
||
<title>Spring MVC Test Framework</title>
|
||
|
||
<sidebar xml:id="spring-mvc-test-origins">
|
||
<title>Standalone project</title>
|
||
|
||
<para>Before inclusion in Spring Framework 3.2, the Spring MVC Test
|
||
framework had already existed as a separate project on GitHub where it
|
||
grew and evolved through actual use, feedback, and the contribution of
|
||
many.</para>
|
||
|
||
<para>The standalone <link
|
||
xl:href="https://github.com/SpringSource/spring-test-mvc">spring-test-mvc
|
||
project</link> is still available on GitHub and can be used in
|
||
conjunction with Spring Framework 3.1.x. Applications upgrading to 3.2
|
||
should replace the <filename>spring-test-mvc</filename> dependency with
|
||
a dependency on <filename>spring-test</filename>.</para>
|
||
|
||
<para>The <filename>spring-test</filename> module uses a different
|
||
package <classname>org.springframework.test.web</classname> but
|
||
otherwise is nearly identical with two exceptions. One is support for
|
||
features new in 3.2 (e.g. asynchronous web requests). The other relates
|
||
to the options for creating a <classname>MockMvc</classname> instance.
|
||
In Spring Framework 3.2, this can only be done through the TestContext
|
||
framework, which provides caching benefits for the loaded
|
||
configuration.</para>
|
||
</sidebar>
|
||
|
||
<para>The <emphasis>Spring MVC Test framework</emphasis> provides first
|
||
class JUnit support for testing client and server-side Spring MVC code
|
||
through a fluent API. Typically it loads the actual Spring configuration
|
||
through the <emphasis>TestContext framework</emphasis> and always uses the
|
||
<classname>DispatcherServlet</classname> to process requests thus
|
||
approximating full integration tests without requiring a running Servlet
|
||
container.</para>
|
||
|
||
<para>Client-side tests are <classname>RestTemplate</classname>-based and
|
||
allow tests for code that relies on the
|
||
<classname>RestTemplate</classname> without requiring a running server to
|
||
respond to the requests.</para>
|
||
|
||
<section xml:id="spring-mvc-test-server">
|
||
<title>Server-Side Tests</title>
|
||
|
||
<para>Before Spring Framework 3.2, the most likely way to test a Spring
|
||
MVC controller was to write a unit test that instantiates the
|
||
controller, injects it with mock or stub dependencies, and then calls
|
||
its methods directly, using a
|
||
<classname>MockHttpServletRequest</classname> and
|
||
<classname>MockHttpServletResponse</classname> where necessary.</para>
|
||
|
||
<para>Although this is pretty easy to do, controllers have many
|
||
annotations, and much remains untested. Request mappings, data binding,
|
||
type conversion, and validation are just a few examples of what isn't
|
||
tested. Furthermore, there are other types of annotated methods such as
|
||
<interfacename>@InitBinder</interfacename>,
|
||
<interfacename>@ModelAttribute</interfacename>, and
|
||
<interfacename>@ExceptionHandler</interfacename> that get invoked as
|
||
part of request processing.</para>
|
||
|
||
<para>The idea behind Spring MVC Test is to be able to re-write those
|
||
controller tests by performing actual requests and generating responses,
|
||
as they would be at runtime, along the way invoking controllers through
|
||
the Spring MVC <classname>DispatcherServlet</classname>. Controllers can
|
||
still be injected with mock dependencies, so tests can remain focused on
|
||
the web layer.</para>
|
||
|
||
<para>Spring MVC Test builds on the familiar "mock" implementations of
|
||
the Servlet API available in the <filename>spring-test</filename>
|
||
module. This allows performing requests and generating responses without
|
||
the need for running in a Servlet container. For the most part
|
||
everything should work as it does at runtime with the exception of JSP
|
||
rendering, which is not available outside a Servlet container.
|
||
Furthermore, if you are familiar with how the
|
||
<classname>MockHttpServletResponse</classname> works, you'll know that
|
||
forwards and redirects are not actually executed. Instead "forwarded"
|
||
and "redirected" URLs are saved and can be asserted in tests. This means
|
||
if you are using JSPs, you can verify the JSP page to which the request
|
||
was forwarded.</para>
|
||
|
||
<para>All other means of rendering including
|
||
<interfacename>@ResponseBody</interfacename> methods and
|
||
<interfacename>View</interfacename> types (besides JSPs) such as
|
||
Freemarker, Velocity, Thymeleaf, and others for rendering HTML, JSON,
|
||
XML, and so on should work as expected, and the response will contain
|
||
the generated content.</para>
|
||
|
||
<para>Below is an example of a test requesting account information in
|
||
JSON format:</para>
|
||
|
||
<programlisting language="java">import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||
|
||
@RunWith(SpringJUnit4ClassRunner.class)
|
||
@WebAppConfiguration
|
||
@ContextConfiguration("test-servlet-context.xml")
|
||
public class ExampleTests {
|
||
|
||
@Autowired
|
||
private WebApplicationContext wac;
|
||
|
||
private MockMvc mockMvc;
|
||
|
||
@Before
|
||
public void setup() {
|
||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
|
||
}
|
||
|
||
@Test
|
||
public void getAccount() throws Exception {
|
||
this.mockMvc.perform(get("/accounts/1").accept(MediaType.parseMediaType("application/json;charset=UTF-8")))
|
||
.andExpect(status().isOk())
|
||
.andExpect(content().contentType("application/json"))
|
||
.andExpect(jsonPath("$.name").value("Lee"));
|
||
}
|
||
|
||
}</programlisting>
|
||
|
||
<para>The test relies on the
|
||
<interfacename>WebApplicationContext</interfacename> support of the
|
||
<emphasis>TestContext framework</emphasis>. It loads Spring
|
||
configuration from an XML configuration file located in the same package
|
||
as the test class (also supports JavaConfig) and injects the created
|
||
<interfacename>WebApplicationContext</interfacename> into the test so a
|
||
<classname>MockMvc</classname> instance can be created with it.</para>
|
||
|
||
<para>The <classname>MockMvc</classname> is then used to perform a
|
||
request to <filename>"/accounts/1"</filename> and verify the resulting
|
||
response status is 200, the response content type is
|
||
<filename>"application/json"</filename>, and response content has a JSON
|
||
property called "name" with the value "Lee". JSON content is inspected
|
||
with the help of Jayway's <link
|
||
xl:href="https://github.com/jayway/JsonPath">JsonPath project</link>.
|
||
There are lots of other options for verifying the result of the
|
||
performed request and those will be discussed later.</para>
|
||
|
||
<section xml:id="spring-mvc-test-server-static-imports">
|
||
<title>Static Imports</title>
|
||
|
||
<para>The fluent API in the example above requires a few static
|
||
imports such as <classname>MockMvcRequestBuilders.*</classname>,
|
||
<classname>MockMvcResultMatchers.*</classname>, and
|
||
<classname>MockMvcBuilders.*</classname>. An easy way to find these
|
||
classes is to search for types matching
|
||
<emphasis>"MockMvc*"</emphasis>. If using Eclipse, be sure to add them
|
||
as "favorite static members" in the Eclipse preferences under
|
||
<emphasis>Java -> Editor -> Content Assist ->
|
||
Favorites</emphasis>. That will allow use of content assist after
|
||
typing the first character of the static method name. Other IDEs (e.g.
|
||
IntelliJ) may not require any additional configuration. Just check the
|
||
support for code completion on static members.</para>
|
||
</section>
|
||
|
||
<section xml:id="spring-mvc-test-server-setup-options">
|
||
<title>Setup Options</title>
|
||
|
||
<para>The goal of server-side test setup is to create an instance of
|
||
<classname>MockMvc</classname> that can be used to perform requests.
|
||
There are two main options.</para>
|
||
|
||
<para>The first option is to point to Spring MVC configuration through
|
||
the <emphasis>TestContext framework</emphasis>, which loads the Spring
|
||
configuration and injects a
|
||
<interfacename>WebApplicationContext</interfacename> into the test to
|
||
use to create a <classname>MockMvc</classname>:</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
@WebAppConfiguration
|
||
@ContextConfiguration("my-servlet-context.xml")
|
||
public class MyWebTests {
|
||
|
||
@Autowired
|
||
private WebApplicationContext wac;
|
||
|
||
private MockMvc mockMvc;
|
||
|
||
@Before
|
||
public void setup() {
|
||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
|
||
}
|
||
|
||
// ...
|
||
|
||
}</programlisting>
|
||
|
||
<para>The second option is to simply register a controller instance
|
||
without loading any Spring configuration. Instead basic Spring MVC
|
||
configuration suitable for testing annotated controllers is
|
||
automatically created. The created configuration is comparable to that
|
||
of the MVC JavaConfig (and the MVC namespace) and can be customized to
|
||
a degree through builder-style methods:</para>
|
||
|
||
<programlisting language="java">public class MyWebTests {
|
||
|
||
private MockMvc mockMvc;
|
||
|
||
@Before
|
||
public void setup() {
|
||
this.mockMvc = MockMvcBuilders.standaloneSetup(new AccountController()).build();
|
||
}
|
||
|
||
// ...
|
||
|
||
}</programlisting>
|
||
|
||
<para>Which option should you use?</para>
|
||
|
||
<para>The <emphasis>"webAppContextSetup"</emphasis> loads the actual
|
||
Spring MVC configuration resulting in a more complete integration
|
||
test. Since the <emphasis>TestContext framework</emphasis> caches the
|
||
loaded Spring configuration, it helps to keep tests running fast even
|
||
as more tests get added. Furthermore, you can inject mock services
|
||
into controllers through Spring configuration, in order to remain
|
||
focused on testing the web layer. Here is an example of declaring a
|
||
mock service with Mockito:</para>
|
||
|
||
<programlisting language="xml"><bean id="accountService" class="org.mockito.Mockito" factory-method="mock">
|
||
<constructor-arg value="org.example.AccountService"/>
|
||
</bean>
|
||
</programlisting>
|
||
|
||
<para>Then you can inject the mock service into the test in order set
|
||
up and verify expectations:</para>
|
||
|
||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||
@WebAppConfiguration
|
||
@ContextConfiguration("test-servlet-context.xml")
|
||
public class AccountTests {
|
||
|
||
@Autowired
|
||
private WebApplicationContext wac;
|
||
|
||
private MockMvc mockMvc;
|
||
|
||
@Autowired
|
||
private AccountService accountService;
|
||
|
||
// ...
|
||
|
||
}</programlisting>
|
||
|
||
<para>The <emphasis>"standaloneSetup"</emphasis> on the other hand is
|
||
a little closer to a unit test. It tests one controller at a time, the
|
||
controller can be injected with mock dependencies manually, and it
|
||
doesn't involve loading Spring configuration. Such tests are more
|
||
focused in style and make it easier to see which controller is being
|
||
tested, whether any specific Spring MVC configuration is required to
|
||
work, and so on. The "standaloneSetup" is also a very convenient way
|
||
to write ad-hoc tests to verify some behavior or to debug an
|
||
issue.</para>
|
||
|
||
<para>Just like with integration vs unit testing, there is no right or
|
||
wrong answer. Using the "standaloneSetup" does imply the need for some
|
||
additional "webAppContextSetup" tests to verify the Spring MVC
|
||
configuration. Alternatively, you can decide write all tests with
|
||
"webAppContextSetup" and always test against actual Spring MVC
|
||
configuration.</para>
|
||
</section>
|
||
|
||
<section xml:id="spring-mvc-test-server-performing-requests">
|
||
<title>Performing Requests</title>
|
||
|
||
<para>To perform requests, use the appropriate HTTP method and
|
||
additional builder-style methods corresponding to properties of
|
||
<classname>MockHttpServletRequest</classname>. For example:</para>
|
||
|
||
<programlisting language="java">mockMvc.perform(post("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON));
|
||
</programlisting>
|
||
|
||
<para>In addition to all the HTTP methods, you can also perform file
|
||
upload requests, which internally creates an instance of
|
||
<classname>MockMultipartHttpServletRequest</classname>:</para>
|
||
|
||
<programlisting language="java">mockMvc.perform(fileUpload("/doc").file("a1", "ABC".getBytes("UTF-8")));
|
||
</programlisting>
|
||
|
||
<para>Query string parameters can be specified in the URI
|
||
template:</para>
|
||
|
||
<programlisting language="java">mockMvc.perform(get("/hotels?foo={foo}", "bar"));
|
||
</programlisting>
|
||
|
||
<para>Or by adding Servlet request parameters:</para>
|
||
|
||
<programlisting language="java">mockMvc.perform(get("/hotels").param("foo", "bar"));
|
||
</programlisting>
|
||
|
||
<para>If application code relies on Servlet request parameters, and
|
||
doesn't check the query string, as is most often the case, then it
|
||
doesn't matter how parameters are added. Keep in mind though that
|
||
parameters provided in the URI template will be decoded while
|
||
parameters provided through the <function>param(...)</function> method
|
||
are expected to be decoded.</para>
|
||
|
||
<para>In most cases it's preferable to leave out the context path and
|
||
the Servlet path from the request URI. If you must test with the full
|
||
request URI, be sure to set the <function>contextPath</function> and
|
||
<function>servletPath</function> accordingly so that request mappings
|
||
will work:</para>
|
||
|
||
<programlisting language="java">mockMvc.perform(get("/app/main/hotels/{id}").contextPath("/app").servletPath("/main"))
|
||
</programlisting>
|
||
|
||
<para>Looking at the above example, it would be cumbersome to set the
|
||
contextPath and servletPath with every performed request. That's why
|
||
you can define default request properties when building the
|
||
<classname>MockMvc</classname>:</para>
|
||
|
||
<programlisting language="java">public class MyWebTests {
|
||
|
||
private MockMvc mockMvc;
|
||
|
||
@Before
|
||
public void setup() {
|
||
mockMvc = standaloneSetup(new AccountController())
|
||
.defaultRequest(get("/")
|
||
.contextPath("/app").servletPath("/main")
|
||
.accept(MediaType.APPLICATION_JSON).build();
|
||
}
|
||
|
||
}</programlisting>
|
||
|
||
<para>The above properties will apply to every request performed
|
||
through the <classname>MockMvc</classname>. If the same property is
|
||
also specified on a given request, it will override the default value.
|
||
That is why, the HTTP method and URI don't matter, when setting
|
||
default request properties, since they must be specified on every
|
||
request.</para>
|
||
</section>
|
||
|
||
<section xml:id="spring-mvc-test-server-defining-expectations">
|
||
<title>Defining Expectations</title>
|
||
|
||
<para>Expectations can be defined by appending one or more
|
||
<function>.andExpect(..)</function> after call to perform the
|
||
request:</para>
|
||
|
||
<programlisting language="java">mockMvc.perform(get("/accounts/1")).andExpect(status().isOk());
|
||
</programlisting>
|
||
|
||
<para><literal>MockMvcResultMatchers.*</literal> defines a number of
|
||
static members, some of which return types with additional methods,
|
||
for asserting the result of the performed request. The assertions fall
|
||
in two general categories.</para>
|
||
|
||
<para>The first category of assertions verify properties of the
|
||
response, i.e the response status, headers, and content. Those are the
|
||
most important things to test for.</para>
|
||
|
||
<para>The second category of assertions go beyond the response, and
|
||
allow inspecting Spring MVC specific constructs such as which
|
||
controller method processed the request, whether an exception was
|
||
raised and handled, what the content of the model is, what view was
|
||
selected, what flash attributes were added, and so on. It is also
|
||
possible to verify Servlet specific constructs such as request and
|
||
session attributes. The following test asserts that binding/validation
|
||
failed:</para>
|
||
|
||
<programlisting language="java">
|
||
mockMvc.perform(post("/persons"))
|
||
.andExpect(status().isOk())
|
||
.andExpect(model().attributeHasErrors("person"));
|
||
</programlisting>
|
||
|
||
<para>Many times when writing tests, it's useful to dump the result of
|
||
the performed request. This can be done as follows, where
|
||
<function>print()</function> is a static import from
|
||
<classname>MockMvcResultHandlers</classname>:</para>
|
||
|
||
<programlisting language="java">mockMvc.perform(post("/persons"))
|
||
.andDo(print())
|
||
.andExpect(status().isOk())
|
||
.andExpect(model().attributeHasErrors("person"));</programlisting>
|
||
|
||
<para>As long as request processing causes an unhandled exception, the
|
||
<function>print()</function> method will print all the available
|
||
result data to <literal>System.out</literal>.</para>
|
||
|
||
<para>In some cases, you may want to get direct access to the result
|
||
and verify something that cannot be verified otherwise. This can be
|
||
done by appending <function>.andReturn()</function> at the end after
|
||
all expectations:</para>
|
||
|
||
<programlisting language="java">MvcResult mvcResult = mockMvc.perform(post("/persons")).andExpect(status().isOk()).andReturn();
|
||
// ...</programlisting>
|
||
|
||
<para>When all tests repeat the same expectations, you can define the
|
||
common expectations once when building the
|
||
<classname>MockMvc</classname>:</para>
|
||
|
||
<programlisting language="java">standaloneSetup(new SimpleController())
|
||
.alwaysExpect(status().isOk())
|
||
.alwaysExpect(content().contentType("application/json;charset=UTF-8"))
|
||
.build()</programlisting>
|
||
|
||
<para>Note that the expectation is <emphasis>always</emphasis> applied
|
||
and cannot be overridden without creating a separate
|
||
<classname>MockMvc</classname> instance.</para>
|
||
|
||
<para>When JSON response content contains hypermedia links created
|
||
with <link
|
||
xl:href="https://github.com/SpringSource/spring-hateoas">Spring
|
||
HATEOAS</link>, the resulting links can be verified:</para>
|
||
|
||
<programlisting language="java">mockMvc.perform(get("/people").accept(MediaType.APPLICATION_JSON))
|
||
.andExpect(jsonPath("$.links[?(@.rel == 'self')].href").value("http://localhost:8080/people"));</programlisting>
|
||
|
||
<para>When XML response content contains hypermedia links created with
|
||
<link xl:href="https://github.com/SpringSource/spring-hateoas">Spring
|
||
HATEOAS</link>, the resulting links can be verified:</para>
|
||
|
||
<programlisting language="java">Map<String, String> ns = Collections.singletonMap("ns", "http://www.w3.org/2005/Atom");
|
||
mockMvc.perform(get("/handle").accept(MediaType.APPLICATION_XML))
|
||
.andExpect(xpath("/person/ns:link[@rel='self']/@href", ns).string("http://localhost:8080/people"));</programlisting>
|
||
</section>
|
||
|
||
<section xml:id="spring-mvc-test-server-filters">
|
||
<title>Filter Registrations</title>
|
||
|
||
<para>When setting up a <classname>MockMvc</classname>, you can
|
||
register one or more <interfacename>Filter</interfacename>
|
||
instances:</para>
|
||
|
||
<programlisting language="java">mockMvc = standaloneSetup(new PersonController()).addFilters(new CharacterEncodingFilter()).build();</programlisting>
|
||
|
||
<para>Registered filters will be invoked through
|
||
<classname>MockFilterChain</classname> from
|
||
<filename>spring-test</filename> and the last filter will delegates to
|
||
the <classname>DispatcherServlet</classname>.</para>
|
||
</section>
|
||
|
||
<section xml:id="spring-mvc-test-server-resources">
|
||
<title>Further Server-Side Test Examples</title>
|
||
|
||
<para>The framework's own tests include <link
|
||
xl:href="https://github.com/SpringSource/spring-framework/tree/master/spring-test-mvc/src/test/java/org/springframework/test/web/servlet/samples">many
|
||
sample tests</link> intended to demonstrate how to use Spring MVC
|
||
Test. Browse these examples for further ideas. Also the <link
|
||
xl:href="https://github.com/SpringSource/spring-mvc-showcase">spring-mvc-showcase</link>
|
||
has full test coverage based on Spring MVC Test.</para>
|
||
</section>
|
||
</section>
|
||
|
||
<section xml:id="spring-mvc-test-client">
|
||
<title>Client-Side REST Tests</title>
|
||
|
||
<para>Client-side tests are for code using the
|
||
<classname>RestTemplate</classname>. The goal is to define expected
|
||
requests and provide "stub" responses:</para>
|
||
|
||
<programlisting language="java">RestTemplate restTemplate = new RestTemplate();
|
||
|
||
MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate);
|
||
mockServer.expect(requestTo("/greeting")).andRespond(withSuccess("Hello world", "text/plain"));
|
||
|
||
// use RestTemplate ...
|
||
|
||
mockServer.verify();</programlisting>
|
||
|
||
<para>In the above example, <classname>MockRestServiceServer</classname>
|
||
-- the central class for client-side REST tests -- configures the
|
||
<classname>RestTemplate</classname> with a custom
|
||
<interfacename>ClientHttpRequestFactory</interfacename> that asserts
|
||
actual requests against expectations and returns "stub" responses. In
|
||
this case we expect a single request to "/greeting" and want to return a
|
||
200 response with "text/plain" content. We could define as many
|
||
additional requests and stub responses as necessary.</para>
|
||
|
||
<para>Once expected requests and stub responses have been defined, the
|
||
<classname>RestTemplate</classname> can be used in client-side code as
|
||
usual. At the end of the tests <literal>mockServer.verify()</literal>
|
||
can be used to verify that all expected requests were performed.</para>
|
||
|
||
<section xml:id="spring-mvc-test-client-static-imports">
|
||
<title>Static Imports</title>
|
||
|
||
<para>Just like with server-side tests, the fluent API for client-side
|
||
tests requires a few static imports. Those are easy to find by
|
||
searching <emphasis>"MockRest*"</emphasis>. Eclipse users should add
|
||
<classname>"MockRestRequestMatchers.*"</classname> and
|
||
<classname>"MockRestResponseCreators.*"</classname> as "favorite
|
||
static members" in the Eclipse preferences under <emphasis>Java ->
|
||
Editor -> Content Assist -> Favorites</emphasis>. That allows
|
||
using content assist after typing the first character of the static
|
||
method name. Other IDEs (e.g. IntelliJ) may not require any additional
|
||
configuration. Just check the support for code completion on static
|
||
members.</para>
|
||
</section>
|
||
|
||
<section xml:id="spring-mvc-test-client-resources">
|
||
<title>Further Examples of Client-side REST Tests</title>
|
||
|
||
<para>Spring MVC Test's own tests include <link
|
||
xl:href="https://github.com/SpringSource/spring-framework/tree/master/spring-test-mvc/src/test/java/org/springframework/test/web/client/samples">example
|
||
tests</link> of client-side REST tests.</para>
|
||
</section>
|
||
</section>
|
||
</section>
|
||
|
||
<section xml:id="testing-examples-petclinic">
|
||
<title>PetClinic Example</title>
|
||
|
||
<para>The PetClinic application, available from the <link
|
||
linkend="new-in-3.0-samples">samples repository</link>, illustrates
|
||
several features of the <emphasis>Spring TestContext Framework</emphasis>
|
||
in a JUnit 4.5+ environment. Most test functionality is included in the
|
||
<classname>AbstractClinicTests</classname>, for which a partial listing is
|
||
shown below:</para>
|
||
|
||
<programlisting language="java">import static org.junit.Assert.assertEquals;
|
||
<lineannotation>// import ...</lineannotation>
|
||
|
||
<emphasis role="bold">@ContextConfiguration</emphasis>
|
||
public abstract class AbstractClinicTests <emphasis role="bold">extends AbstractTransactionalJUnit4SpringContextTests</emphasis> {
|
||
|
||
<emphasis role="bold">@Autowired</emphasis>
|
||
protected Clinic clinic;
|
||
|
||
@Test
|
||
public void getVets() {
|
||
Collection<Vet> vets = this.clinic.getVets();
|
||
assertEquals("JDBC query must show the same number of vets",
|
||
<emphasis role="bold">super.countRowsInTable("VETS")</emphasis>, vets.size());
|
||
Vet v1 = EntityUtils.getById(vets, Vet.class, 2);
|
||
assertEquals("Leary", v1.getLastName());
|
||
assertEquals(1, v1.getNrOfSpecialties());
|
||
assertEquals("radiology", (v1.getSpecialties().get(0)).getName());
|
||
<lineannotation>// ...</lineannotation>
|
||
}
|
||
|
||
<lineannotation>// ...</lineannotation>
|
||
}</programlisting>
|
||
|
||
<para>Notes:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>This test case extends the
|
||
<classname>AbstractTransactionalJUnit4SpringContextTests</classname>
|
||
class, from which it inherits configuration for Dependency Injection
|
||
(through the
|
||
<classname>DependencyInjectionTestExecutionListener</classname>) and
|
||
transactional behavior (through the
|
||
<classname>TransactionalTestExecutionListener</classname>).</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>The <literal>clinic</literal> instance variable — the
|
||
application object being tested — is set by Dependency Injection
|
||
through <interfacename>@Autowired</interfacename> semantics.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>The <methodname>testGetVets()</methodname> method illustrates
|
||
how you can use the inherited
|
||
<methodname>countRowsInTable()</methodname> method to easily verify
|
||
the number of rows in a given table, thus verifying correct behavior
|
||
of the application code being tested. This allows for stronger tests
|
||
and lessens dependency on the exact test data. For example, you can
|
||
add additional rows in the database without breaking tests.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>Like many integration tests that use a database, most of the
|
||
tests in <classname>AbstractClinicTests</classname> depend on a
|
||
minimum amount of data already in the database before the test cases
|
||
run. Alternatively, you might choose to populate the database within
|
||
the test fixture set up of your test cases — again, within the same
|
||
transaction as the tests.</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<para>The PetClinic application supports three data access technologies:
|
||
JDBC, Hibernate, and JPA. By declaring
|
||
<interfacename>@ContextConfiguration</interfacename> without any specific
|
||
resource locations, the <classname>AbstractClinicTests</classname> class
|
||
will have its application context loaded from the default location,
|
||
<literal>AbstractClinicTests-context.xml</literal>, which declares a
|
||
common <classname>DataSource</classname>. Subclasses specify additional
|
||
context locations that must declare a
|
||
<interfacename>PlatformTransactionManager</interfacename> and a concrete
|
||
implementation of <interfacename>Clinic</interfacename>.</para>
|
||
|
||
<para>For example, the Hibernate implementation of the PetClinic tests
|
||
contains the following implementation. For this example,
|
||
<classname>HibernateClinicTests</classname> does not contain a single line
|
||
of code: we only need to declare
|
||
<interfacename>@ContextConfiguration</interfacename>, and the tests are
|
||
inherited from <classname>AbstractClinicTests</classname>. Because
|
||
<interfacename>@ContextConfiguration</interfacename> is declared without
|
||
any specific resource locations, the <emphasis>Spring TestContext
|
||
Framework</emphasis> loads an application context from all the beans
|
||
defined in <literal>AbstractClinicTests-context.xml</literal> (i.e., the
|
||
inherited locations) and
|
||
<literal>HibernateClinicTests-context.xml</literal>, with
|
||
<literal>HibernateClinicTests-context.xml</literal> possibly overriding
|
||
beans defined in
|
||
<literal>AbstractClinicTests-context.xml</literal>.</para>
|
||
|
||
<programlisting language="java"><emphasis role="bold">@ContextConfiguration</emphasis>
|
||
public class HibernateClinicTests extends AbstractClinicTests { }
|
||
</programlisting>
|
||
|
||
<para>In a large-scale application, the Spring configuration is often
|
||
split across multiple files. Consequently, configuration locations are
|
||
typically specified in a common base class for all application-specific
|
||
integration tests. Such a base class may also add useful instance
|
||
variables — populated by Dependency Injection, naturally — such as a
|
||
<classname>SessionFactory</classname> in the case of an application using
|
||
Hibernate.</para>
|
||
|
||
<para>As far as possible, you should have exactly the same Spring
|
||
configuration files in your integration tests as in the deployed
|
||
environment. One likely point of difference concerns database connection
|
||
pooling and transaction infrastructure. If you are deploying to a
|
||
full-blown application server, you will probably use its connection pool
|
||
(available through JNDI) and JTA implementation. Thus in production you
|
||
will use a <classname>JndiObjectFactoryBean</classname> or
|
||
<literal><jee:jndi-lookup></literal> for the
|
||
<classname>DataSource</classname> and
|
||
<classname>JtaTransactionManager</classname>. JNDI and JTA will not be
|
||
available in out-of-container integration tests, so you should use a
|
||
combination like the Commons DBCP <classname>BasicDataSource</classname>
|
||
and <classname>DataSourceTransactionManager</classname> or
|
||
<classname>HibernateTransactionManager</classname> for them. You can
|
||
factor out this variant behavior into a single XML file, having the choice
|
||
between application server and a 'local' configuration separated from all
|
||
other configuration, which will not vary between the test and production
|
||
environments. In addition, it is advisable to use properties files for
|
||
connection settings. See the PetClinic application for an example.</para>
|
||
</section>
|
||
</section>
|
||
|
||
<section xml:id="testing-resources">
|
||
<title>Further Resources</title>
|
||
|
||
<para>Consult the following resources for more information about
|
||
testing:</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para><link xl:href="http://www.junit.org/">JUnit</link>: <quote>
|
||
<emphasis>A programmer-oriented testing framework for Java</emphasis>
|
||
</quote>. Used by the Spring Framework in its test suite.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><link xl:href="http://testng.org/">TestNG</link>: A testing
|
||
framework inspired by JUnit with added support for Java 5 annotations,
|
||
test groups, data-driven testing, distributed testing, etc.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><link
|
||
xl:href="http://www.mockobjects.com/">MockObjects.com</link>: Web site
|
||
dedicated to mock objects, a technique for improving the design of code
|
||
within test-driven development.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><link xl:href="http://en.wikipedia.org/wiki/Mock_Object">"Mock
|
||
Objects"</link>: Article in Wikipedia.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><link xl:href="http://www.easymock.org/">EasyMock</link>: Java
|
||
library <quote> <emphasis>that provides Mock Objects for interfaces (and
|
||
objects through the class extension) by generating them on the fly using
|
||
Java's proxy mechanism.</emphasis> </quote> Used by the Spring Framework
|
||
in its test suite.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><link xl:href="http://www.jmock.org/">JMock</link>: Library that
|
||
supports test-driven development of Java code with mock objects.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><link xl:href="http://mockito.org/">Mockito</link>: Java mock
|
||
library based on the <link
|
||
xl:href="http://xunitpatterns.com/Test%20Spy.html">test spy</link>
|
||
pattern.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><link xl:href="http://dbunit.sourceforge.net/">DbUnit</link>:
|
||
JUnit extension (also usable with Ant and Maven) targeted for
|
||
database-driven projects that, among other things, puts your database
|
||
into a known state between test runs.</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para><link xl:href="http://grinder.sourceforge.net/">The
|
||
Grinder</link>: Java load testing framework.</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</section>
|
||
</chapter>
|