1968 lines
94 KiB
XML
1968 lines
94 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
|
<chapter id="testing">
|
|
<title>Testing</title>
|
|
|
|
<section id="testing-introduction">
|
|
<title>Introduction to 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 Spring
|
|
Framework <link linkend="integration-testing">integration testing</link>.
|
|
(A thorough treatment of testing in the enterprise is beyond the scope of
|
|
this chapter.)</para>
|
|
</section>
|
|
|
|
<section 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 id="mock-objects">
|
|
<title>Mock objects</title>
|
|
|
|
<section 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 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 <ulink
|
|
url="http://www.easymock.org">EasyMock</ulink> or existing Servlet API
|
|
mock objects such as <ulink
|
|
url="http://www.mockobjects.com">MockObjects</ulink>.</para>
|
|
</section>
|
|
|
|
<section 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 id="unit-testing-support-classes">
|
|
<title>Unit testing support classes</title>
|
|
|
|
<section 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 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 4+, TestNG, and so on 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 id="integration-testing">
|
|
<title>Integration testing</title>
|
|
|
|
<section 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 got 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>Legacy JUnit 3.8 class hierarchy is deprecated</title>
|
|
|
|
<para>As of Spring 3.0, the legacy JUnit 3.8 base class hierarchy (for
|
|
example,
|
|
<classname>AbstractDependencyInjectionSpringContextTests</classname>,
|
|
<classname>AbstractTransactionalDataSourceSpringContextTests</classname>,
|
|
etc.) is officially deprecated and will be removed in a later release.
|
|
Migrate this code to the <link linkend="testcontext-framework">Spring
|
|
TestContext Framework</link>.</para>
|
|
</warning>
|
|
</section>
|
|
|
|
<section 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 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 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 could reduce
|
|
productivity.</para>
|
|
|
|
<para>Test classes provide an array containing the resource locations
|
|
of XML configuration metadata — typically in the classpath — that is
|
|
used to configure the application. These locations are the same as or
|
|
similar to the list of configuration locations 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 fixture),
|
|
and subsequent test execution is much faster. 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 — a Spring testing support mechanism causes the
|
|
test fixture to reload the configurations and rebuilds the application
|
|
context before executing the next test.</para>
|
|
|
|
<para>See context management and caching with the <link
|
|
linkend="testcontext-ctx-management">TestContext
|
|
Framework</link>.</para>
|
|
</section>
|
|
|
|
<section 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 set up for individual test cases.</para>
|
|
|
|
<para>As an example, consider the scenario where we have a class,
|
|
<classname>HibernateTitleDao</classname>, that performs data access
|
|
logic for say, the <classname>Title</classname> domain object. We want
|
|
to write integration tests that test all of the following
|
|
areas:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>The Spring configuration: basically, is everything related
|
|
to the configuration of the
|
|
<classname>HibernateTitleDao</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>HibernateTitleDao</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 id="testing-tx">
|
|
<title>Transaction management</title>
|
|
|
|
<para>One common issue in tests that access a real database is their
|
|
affect 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 transactional semantics. In
|
|
addition, if test methods delete the contents of selected tables while
|
|
running within a transaction, 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 your test class 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 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>SimpleJdbcTemplate</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 id="integration-testing-support-jdbc">
|
|
<title>JDBC testing support</title>
|
|
|
|
<para>The <literal>org.springframework.test.jdbc</literal> package
|
|
contains <classname>SimpleJdbcTestUtils</classname>, which is a
|
|
Java-5-based collection of JDBC related utility functions intended to
|
|
simplify standard database testing scenarios. <emphasis>Note that <link
|
|
linkend="testcontext-support-classes-junit38"><classname>AbstractTransactionalJUnit38SpringContextTests</classname></link>,
|
|
<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>SimpleJdbcTestUtils</classname> internally.</emphasis></para>
|
|
</section>
|
|
|
|
<section id="integration-testing-annotations">
|
|
<title>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>. Specifically,
|
|
<interfacename>@ContextConfiguration</interfacename> defines the
|
|
application context resource <literal>locations</literal> to load as
|
|
well as the <interfacename>ContextLoader</interfacename> strategy to
|
|
use for loading the context.</para>
|
|
|
|
<programlisting language="java">@ContextConfiguration(locations="example/test-context.xml", loader=CustomContextLoader.class)
|
|
public class CustomConfiguredApplicationContextTests {
|
|
<lineannotation>// class body...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<note>
|
|
<para><interfacename>@ContextConfiguration</interfacename>
|
|
supports <emphasis>inherited</emphasis> resource locations by
|
|
default. See <link linkend="testcontext-ctx-management">Context
|
|
management and caching</link> and JavaDoc for an example and
|
|
further details.</para>
|
|
</note>
|
|
</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> (i.e., modified or corrupted in some manner)
|
|
during the execution of a test and should be closed,
|
|
regardless of whether the test passed.
|
|
<interfacename>@DirtiesContext</interfacename> is supported in
|
|
the following scenarios:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>After the current test class, when declared on a class
|
|
with class mode set to <literal>AFTER_CLASS</literal>, which is
|
|
the default class mode.</para>
|
|
</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></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>After the current test, when declared on a method.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Use this annotation if a test has modified the context (for
|
|
example, by replacing a bean definition). Subsequent tests are
|
|
supplied a new context.</para>
|
|
|
|
<warning>
|
|
<title>Limitations of
|
|
<interfacename>@DirtiesContext</interfacename> at the class level</title>
|
|
|
|
<para>JUnit 4+ and TestNG both support class-level lifecycle
|
|
callbacks — for example, via <interfacename>@BeforeClass</interfacename>
|
|
and <interfacename>@AfterClass</interfacename> annotations. Consequently,
|
|
<interfacename>@DirtiesContext</interfacename> can be used at the class level
|
|
with these frameworks. JUnit 3.x, however, does not support
|
|
<emphasis>before class</emphasis> or <emphasis>after class</emphasis>
|
|
lifecycle callbacks. Thus, in a JUnit 3.x environment
|
|
<interfacename>@DirtiesContext</interfacename> is only supported
|
|
on methods and not at the class level.</para>
|
|
</warning>
|
|
|
|
<para>If class-level usage of <interfacename>@DirtiesContext</interfacename>
|
|
is supported — for example, with JUnit 4.5+ or TestNG —
|
|
you can use
|
|
<interfacename>@DirtiesContext</interfacename> 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>
|
|
|
|
<programlisting language="java">@DirtiesContext
|
|
public class ContextDirtyingTests {
|
|
<lineannotation>// some tests that result in the Spring container being dirtied</lineannotation>
|
|
}</programlisting>
|
|
|
|
<programlisting language="java">@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
|
|
public class ContextDirtyingTests {
|
|
<lineannotation>// some tests that result in the Spring container being dirtied</lineannotation>
|
|
}</programlisting>
|
|
|
|
<programlisting language="java">@DirtiesContext
|
|
@Test
|
|
public void testProcessWhichDirtiesAppCtx() {
|
|
<lineannotation>// some logic that results in the Spring container being dirtied</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>When an application context is marked
|
|
<emphasis>dirty</emphasis>, it is removed from the testing
|
|
framework's cache and closed; thus the underlying Spring container
|
|
is rebuilt for any subsequent test that requires a context with the
|
|
same set of resource locations.</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>
|
|
are used in conjunction with
|
|
<interfacename>@ContextConfiguration</interfacename>.</para>
|
|
|
|
<programlisting language="java">@ContextConfiguration
|
|
@TestExecutionListeners({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 is to
|
|
be used to drive transactions can be explicitly configured 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
|
|
@TransactionConfiguration(transactionManager="txMgr", defaultRollback=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 your transaction
|
|
manager bean is named "transactionManager" and if you want
|
|
transactions to roll back automatically, 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">@Rollback(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
|
|
through the <interfacename>@Transactional</interfacename>
|
|
annotation.</para>
|
|
|
|
<programlisting language="java">@BeforeTransaction
|
|
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
|
|
through the <interfacename>@Transactional</interfacename>
|
|
annotation.</para>
|
|
|
|
<programlisting language="java">@AfterTransaction
|
|
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">@NotTransactional
|
|
@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>
|
|
|
|
<para>The following annotations are <emphasis>only</emphasis> supported
|
|
when used in conjunction with JUnit (that is, with the <link
|
|
linkend="testcontext-junit4-runner">SpringJUnit4ClassRunner</link> or
|
|
the <link linkend="testcontext-support-classes-junit38">JUnit
|
|
3.8.2</link> and <link
|
|
linkend="testcontext-support-classes-junit4">JUnit 4.5+</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">@IfProfileValue(name="java.vendor", value="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">@IfProfileValue(name="test-groups", values={"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">@ProfileValueSourceConfiguration(CustomProfileValueSource.class)
|
|
public class CustomProfileValueSourceTests {
|
|
<lineannotation>// class body...</lineannotation>
|
|
}</programlisting>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis
|
|
role="bold"><interfacename>@ExpectedException</interfacename></emphasis></para>
|
|
|
|
<para>Indicates that the annotated test method is expected to throw
|
|
an exception during execution. The type of the expected exception is
|
|
provided in the annotation, and if an instance of the exception is
|
|
thrown during the test method execution then the test passes.
|
|
Likewise if an instance of the exception is <emphasis>not</emphasis>
|
|
thrown during the test method execution then the test fails.</para>
|
|
|
|
<programlisting language="java">@ExpectedException(SomeBusinessException.class)
|
|
public void testProcessRainyDayScenario() {
|
|
<lineannotation>// some logic that should result in an <classname>Exception</classname> being thrown</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>Using Spring's
|
|
<interfacename>@ExpectedException</interfacename> annotation in
|
|
conjunction with JUnit 4's
|
|
<interfacename>@Test(expected=...)</interfacename> configuration
|
|
would lead to an unresolvable conflict. Developers must therefore
|
|
choose one or the other when integrating with JUnit 4, in which case
|
|
it is generally preferable to use the explicit JUnit 4
|
|
configuration.</para>
|
|
</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">@Timed(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 4's
|
|
<interfacename>@Test(timeout=...)</interfacename> support.
|
|
Specifically, due to the manner in which JUnit 4 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">@Repeat(10)
|
|
@Test
|
|
public void testProcessRepeatedly() {
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>The following non-test-specific annotations are supported with
|
|
standard semantics for all configurations of the Spring TestContext
|
|
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>@Provider</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>
|
|
</section>
|
|
|
|
<section 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, whether JUnit 3.8.2, JUnit
|
|
4.5+, TestNG 5.12, and so on. 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 3.8.2, JUnit 4.5+, and
|
|
TestNG 5.12 in the form of <literal>abstract</literal> support classes.
|
|
For JUnit 4.5+, the framework also provides a custom
|
|
<interfacename>Runner</interfacename> that allows one to write test
|
|
classes that 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, 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 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> interface. A
|
|
<classname>TestContextManager</classname> is created on a per-test
|
|
basis. 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. Consult the JavaDoc and
|
|
the Spring test suite for further information and examples of various
|
|
configurations.</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><classname>TestContext</classname>: Encapsulates the context
|
|
in which a test is executed, agnostic of the actual testing
|
|
framework in use.</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 three
|
|
<interfacename>TestExecutionListener</interfacename>
|
|
implementations that are configured by default:
|
|
<classname>DependencyInjectionTestExecutionListener</classname>,
|
|
<classname>DirtiesContextTestExecutionListener</classname>, and
|
|
<classname>TransactionalTestExecutionListener</classname>.
|
|
Respectively, they support dependency injection of the test
|
|
instance, handling of the
|
|
<interfacename>@DirtiesContext</interfacename> annotation, and
|
|
transactional test execution with default rollback semantics.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>The following three 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 id="testcontext-ctx-management">
|
|
<title>Context management and caching</title>
|
|
|
|
<para>Each <classname>TestContext</classname> provides context
|
|
management and caching support for the test instance for which it is
|
|
responsible. Test instances do not automatically receive access to the
|
|
configured <classname>ApplicationContext</classname>. However, if a
|
|
test class implements the
|
|
<interfacename>ApplicationContextAware</interfacename> interface, a
|
|
reference to the <classname>ApplicationContext</classname> is supplied
|
|
to the test instance, if the
|
|
<classname>DependencyInjectionTestExecutionListener</classname> is
|
|
configured, which is the default.
|
|
<classname>AbstractJUnit38SpringContextTests</classname>,
|
|
<classname>AbstractJUnit4SpringContextTests</classname>, and
|
|
<classname>AbstractTestNGSpringContextTests</classname> already
|
|
implement <interfacename>ApplicationContextAware</interfacename> and
|
|
therefore provide this functionality out-of-the-box.</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>
|
|
</tip>
|
|
|
|
<para>In contrast to the now deprecated JUnit 3.8 legacy class
|
|
hierarchy, test classes that use the TestContext framework do not need
|
|
to override any <literal>protected</literal> instance methods to
|
|
configure their application context. Rather, configuration is achieved
|
|
merely 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>, the
|
|
configured <interfacename>ContextLoader</interfacename> determines how
|
|
and whether to load a context from a default set of locations. For
|
|
example, <classname>GenericXmlContextLoader</classname> , which is the
|
|
default <interfacename>ContextLoader</interfacename>, generates 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 <literal>"classpath:/com/example/MyTest-context.xml"</literal></lineannotation>
|
|
<emphasis role="bold">@ContextConfiguration</emphasis>
|
|
public class MyTest {
|
|
<lineannotation>// class body...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>If the default location does not suit your needs, you can
|
|
configure explicitly the <literal>locations</literal> attribute of
|
|
<interfacename>@ContextConfiguration</interfacename> with an array
|
|
that contains the resource locations of XML configuration metadata
|
|
(assuming an XML-capable <interfacename>ContextLoader</interfacename>
|
|
has been configured) — typically in the classpath<!--*what* is in the classpath? This sentence is confusing. Please revise.-->
|
|
— used to configure the application. (See the following code example.)
|
|
This location will be the same, or nearly the same, as the list of
|
|
configuration locations specified in <literal>web.xml</literal> or
|
|
other deployment configuration. Alternatively, you can implement and
|
|
configure your own custom
|
|
<interfacename>ContextLoader</interfacename>.</para>
|
|
|
|
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
|
<lineannotation>// ApplicationContext will be loaded from <literal>"/applicationContext.xml"</literal> and <literal>"/applicationContext-test.xml"</literal></lineannotation>
|
|
<lineannotation>// in the root of the classpath</lineannotation>
|
|
<emphasis role="bold">@ContextConfiguration({"/applicationContext.xml", "/applicationContext-test.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 <literal>value</literal> attribute. Thus, if you do not need
|
|
to configure a custom <interfacename>ContextLoader</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.
|
|
<interfacename>@ContextConfiguration</interfacename> also supports a
|
|
boolean <literal>inheritLocations</literal> attribute that denotes
|
|
whether resource locations from superclasses should be
|
|
<emphasis>inherited</emphasis>. The default value is
|
|
<literal>true</literal>, which means that an annotated class inherits
|
|
the resource locations defined by an annotated superclass.
|
|
Specifically, the resource locations for an annotated class are
|
|
appended to the list of resource locations defined by an annotated
|
|
superclass. Thus, subclasses have the option of
|
|
<emphasis>extending</emphasis> the list of resource locations. In the
|
|
following example, the
|
|
<interfacename>ApplicationContext</interfacename> for
|
|
<classname>ExtendedTest</classname> is loaded from "/base-context.xml"
|
|
<emphasis role="bold">and</emphasis> "/extended-context.xml", in that
|
|
order. Beans defined in "/extended-context.xml" may therefore override
|
|
those defined in "/base-context.xml".</para>
|
|
|
|
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
|
<lineannotation>// ApplicationContext will be loaded from <literal>"/base-context.xml"</literal> in the root of the classpath</lineannotation>
|
|
<emphasis role="bold">@ContextConfiguration("/base-context.xml")</emphasis>
|
|
public class BaseTest {
|
|
<lineannotation>// class body...</lineannotation>
|
|
}
|
|
|
|
<lineannotation>// ApplicationContext will be loaded from <literal>"/base-context.xml"</literal> and <literal>"/extended-context.xml"</literal></lineannotation>
|
|
<lineannotation>// in the root of the classpath</lineannotation>
|
|
<emphasis role="bold">@ContextConfiguration("/extended-context.xml")</emphasis>
|
|
public class ExtendedTest extends BaseTest {
|
|
<lineannotation>// class body...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>If <literal>inheritLocations</literal> is set to
|
|
<literal>false</literal>, the resource locations for the annotated
|
|
class shadows and effectively replaces any resource locations defined
|
|
by a superclass.</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 fixture),
|
|
and subsequent test execution is much faster. In the unlikely case
|
|
that a test dirties (modifies)<!--dirty means modify? If not, revise to say what it does mean. If corrupted, say that.-->
|
|
the application context, requiring reloading — for example, by
|
|
changing a bean definition or the state of an application object —
|
|
you can annotate your test method with
|
|
<interfacename>@DirtiesContext</interfacename> (assuming
|
|
<classname>DirtiesContextTestExecutionListener</classname> has been
|
|
configured, which is the default) to cause the test fixture to reload
|
|
the configurations and rebuild the application context before
|
|
executing the next test. </para>
|
|
</section>
|
|
|
|
<section id="testcontext-fixture-di">
|
|
<title>Dependency Injection of test fixtures</title>
|
|
|
|
<para>When you configure the
|
|
<classname>DependencyInjectionTestExecutionListener</classname> —
|
|
which is configured by default through the
|
|
<interfacename>@TestExecutionListeners</interfacename> annotation —
|
|
the dependencies of your test instances are
|
|
<emphasis>injected</emphasis> from beans in the application context
|
|
you configured through
|
|
<interfacename>@ContextConfiguration</interfacename> by 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, you
|
|
can use Spring's <interfacename>@Autowired</interfacename> annotation
|
|
or the <interfacename>@Resource</interfacename> annotation from JSR
|
|
250. The semantics for both are consistent throughout the Spring
|
|
Framework. For example, if you prefer <link
|
|
linkend="beans-factory-autowire"><emphasis>autowiring by
|
|
type</emphasis></link>, annotate your setter methods or fields with
|
|
<interfacename>@Autowired</interfacename>. If you prefer to have your
|
|
dependencies injected <emphasis>by name</emphasis>, annotate your
|
|
setter methods or fields with
|
|
<interfacename>@Resource</interfacename>.</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> for constructors has no
|
|
effect for test classes.</para>
|
|
</tip>
|
|
|
|
<para>Because <interfacename>@Autowired</interfacename> performs <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>@Resource</interfacename> for injection <emphasis>by
|
|
name</emphasis>. 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("titleDao")</methodname>. A
|
|
third option is to use <interfacename>@Autowired</interfacename> in
|
|
conjunction with <interfacename>@Qualifier</interfacename>.</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>@Resource</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 a class,
|
|
<classname>HibernateTitleDao</classname>, as outlined in the <link
|
|
linkend="testing-fixture-di">Goals</link> section. (We will look at
|
|
the application context configuration after all sample code listings.)
|
|
A JUnit 4-based implementation of the test class itself uses
|
|
<interfacename>@Autowired</interfacename> for field injection.
|
|
<!--Refer to following code listing; indicate what it shows.--></para>
|
|
|
|
<note>
|
|
<para>The dependency injection behavior in the following code
|
|
listings is not in any way specific to JUnit 4. 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>
|
|
|
|
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
|
<lineannotation>// specifies the Spring configuration to load for this test fixture</lineannotation>
|
|
<emphasis role="bold">@ContextConfiguration("daos.xml")</emphasis>
|
|
public final class HibernateTitleDaoTests {
|
|
|
|
<lineannotation>// this instance will be dependency injected <emphasis
|
|
role="bold">by type</emphasis></lineannotation>
|
|
<emphasis role="bold">@Autowired</emphasis>
|
|
private HibernateTitleDao titleDao;
|
|
|
|
public void testLoadTitle() throws Exception {
|
|
Title title = this.titleDao.loadTitle(new Long(10));
|
|
assertNotNull(title);
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>Alternatively, you can configure the class to use
|
|
<interfacename>@Autowired</interfacename> for setter injection.</para>
|
|
|
|
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
|
<lineannotation>// specifies the Spring configuration to load for this test fixture</lineannotation>
|
|
<emphasis role="bold">@ContextConfiguration("daos.xml")</emphasis>
|
|
public final class HibernateTitleDaoTests {
|
|
|
|
<lineannotation>// this instance will be dependency injected <emphasis
|
|
role="bold">by type</emphasis></lineannotation>
|
|
private HibernateTitleDao titleDao;
|
|
|
|
<emphasis role="bold">@Autowired</emphasis>
|
|
public void setTitleDao(HibernateTitleDao titleDao) {
|
|
this.titleDao = titleDao;
|
|
}
|
|
|
|
public void testLoadTitle() throws Exception {
|
|
Title title = this.titleDao.loadTitle(new Long(10));
|
|
assertNotNull(title);
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>Here is an example of <interfacename>@Resource</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("daos.xml")</emphasis>
|
|
public final class HibernateTitleDaoTests {
|
|
|
|
<lineannotation>// this instance will be dependency injected <emphasis
|
|
role="bold">by name</emphasis></lineannotation>
|
|
<emphasis role="bold">@Resource</emphasis>
|
|
private HibernateTitleDao titleDao;
|
|
|
|
public void testLoadTitle() throws Exception {
|
|
Title title = this.titleDao.loadTitle(new Long(10));
|
|
assertNotNull(title);
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>Here is an example of <interfacename>@Resource</interfacename>
|
|
for setter injection.</para>
|
|
|
|
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
|
<lineannotation>// specifies the Spring configuration to load for this test fixture</lineannotation>
|
|
<emphasis role="bold">@ContextConfiguration("daos.xml")</emphasis>
|
|
public final class HibernateTitleDaoTests {
|
|
|
|
<lineannotation>// this instance will be dependency injected <emphasis
|
|
role="bold">by name</emphasis></lineannotation>
|
|
private HibernateTitleDao titleDao;
|
|
|
|
<emphasis role="bold">@Resource</emphasis>
|
|
public void setTitleDao(HibernateTitleDao titleDao) {
|
|
this.titleDao = titleDao;
|
|
}
|
|
|
|
public void testLoadTitle() throws Exception {
|
|
Title title = this.titleDao.loadTitle(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>daos.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-3.0.xsd">
|
|
|
|
<lineannotation><!-- this bean will be injected into the <classname>HibernateTitleDaoTests</classname> class --></lineannotation>
|
|
<bean id="<emphasis role="bold">titleDao</emphasis>" class="<emphasis
|
|
role="bold">com.foo.dao.hibernate.HibernateTitleDao</emphasis>">
|
|
<property name="sessionFactory" ref="sessionFactory"/>
|
|
</bean>
|
|
|
|
<bean id="sessionFactory"
|
|
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
|
|
<lineannotation><!-- dependencies elided for clarity --></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 and use the
|
|
<interfacename>@Qualifier</interfacename> annotation to indicate a
|
|
specific target bean as follows:</para>
|
|
|
|
<programlisting language="java"><lineannotation>// ...</lineannotation>
|
|
|
|
@Autowired
|
|
@Override
|
|
public void setDataSource(<emphasis role="bold">@Qualifier("myDataSource")</emphasis> DataSource dataSource) {
|
|
super.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). If there is only one
|
|
<interfacename>DataSource</interfacename> bean to begin with, then
|
|
the qualifier does not have any effect, independent from the bean
|
|
name of that single matching bean.
|
|
<!--What about the bean name of the single matching bean? Relate to rest of the sentence.--></para>
|
|
|
|
<para>Alternatively, consider using the
|
|
<interfacename>@Resource</interfacename> annotation on such
|
|
overridden setter methods, defining the target bean name explicitly,
|
|
with no type matching semantics. Note that this
|
|
<!--Revise preceding: indicate *what* always points to a bean with that specific name.-->always
|
|
points to a bean with that specific name, no matter whether there is
|
|
one or more beans of the given type.</para>
|
|
|
|
<programlisting language="java"><lineannotation>// ...</lineannotation>
|
|
|
|
<emphasis role="bold">@Resource("myDataSource")</emphasis>
|
|
@Override
|
|
public void setDataSource(DataSource dataSource) {
|
|
super.setDataSource(dataSource);
|
|
}
|
|
|
|
<lineannotation>// ...</lineannotation></programlisting>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="testcontext-tx">
|
|
<title>Transaction management</title>
|
|
|
|
<para>In the TestContext framework, transactions are managed by the
|
|
<classname>TransactionalTestExecutionListener</classname>, which is
|
|
configured through the
|
|
<interfacename>@TestExecutionListeners</interfacename> annotation 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.</para>
|
|
|
|
<para>For class-level transaction configuration (that is, setting the
|
|
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-junit38"><classname>AbstractTransactionalJUnit38SpringContextTests</classname></link>,
|
|
<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 (for example, 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> (for example, methods
|
|
annotated with JUnit 4's @Before) and any <emphasis>after
|
|
methods</emphasis> (such as methods annotated with JUnit 4's @After)
|
|
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 4 based example displays a fictitious
|
|
integration testing scenario highlighting several transaction-related
|
|
annotations. Consult the <link
|
|
linkend="integration-testing-annotations">annotation support</link>
|
|
section of the reference manual
|
|
<!--If by reference manual you mean this manual, delete *of the reference manual*. If you mean another book, give name of it.-->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 id="testcontext-tx-false-positives"/>
|
|
<note>
|
|
<title>Avoid false positives when testing ORM code</title>
|
|
|
|
<para>When you test code involving an ORM framework such as JPA or
|
|
Hibernate, <emphasis>flush</emphasis> the underlying session within
|
|
test methods
|
|
<!--Revise remainder of sentence:
|
|
*,which updates (note comma and s) the state of the session*
|
|
OR *that (not *which*) update the state of the session.*
|
|
Two different meanings.--> which update the state of the
|
|
session. Failing to flush the ORM framework's 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.</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 id="testcontext-support-classes">
|
|
<title>TestContext support classes</title>
|
|
|
|
<section id="testcontext-support-classes-junit38">
|
|
<title>JUnit 3.8 support classes</title>
|
|
|
|
<para>The
|
|
<literal>org.springframework.test.context.junit38</literal> package
|
|
provides support classes for JUnit 3.8 based test cases.</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><classname>AbstractJUnit38SpringContextTests</classname>:
|
|
Abstract <classname>TestCase</classname> that integrates the
|
|
<emphasis>Spring TestContext Framework</emphasis> with explicit
|
|
<classname>ApplicationContext</classname> testing support in a
|
|
JUnit 3.8 environment. When you extend the
|
|
<classname>AbstractJUnit38SpringContextTests</classname> class,
|
|
you need access to the following <literal>protected</literal>
|
|
instance variables:
|
|
<!--Either provide more variables or change *variables* above to *variable*.
|
|
Also revise to indicate: you need access to this variable *in order* to extend
|
|
aforementioned class? Not sure what preceding is saying.
|
|
Next bullet point says when you extend the class, you *have* access
|
|
to variables. i.e. extending class is what gives you access.--></para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal>applicationContext</literal>: Perform
|
|
explicit bean lookups or test the state of the context as a
|
|
whole.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><classname>AbstractTransactionalJUnit38SpringContextTests</classname>:
|
|
Abstract <emphasis>transactional</emphasis> extension of
|
|
<classname>AbstractJUnit38SpringContextTests</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 the
|
|
<classname>AbstractTransactionalJUnit38SpringContextTests</classname>
|
|
class, you will have access to the following
|
|
<literal>protected</literal> instance variables:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal>applicationContext</literal>: Inherited from
|
|
the <classname>AbstractJUnit38SpringContextTests</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>simpleJdbcTemplate</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>
|
|
</section>
|
|
|
|
<section id="testcontext-support-classes-junit4">
|
|
<title>JUnit 4.5+ 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>: Perform
|
|
explicit bean lookups or 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>simpleJdbcTemplate</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 extend directly 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 id="testcontext-junit4-runner">
|
|
<title>Custom JUnit 4.5+ 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.6, and 4.7). By annotating test classes with
|
|
<literal>@RunWith(SpringJUnit4ClassRunner.class)</literal>,
|
|
developers can implement standard JUnit 4.5+ 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 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>: Perform
|
|
explicit bean lookups or 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>simpleJdbcTemplate</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 id="testing-examples-petclinic">
|
|
<title>PetClinic example</title>
|
|
|
|
<para>The PetClinic application, available from the <link linkend="new-in-3-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 testing 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. You might, however, choose to populate the database in
|
|
<!--do you mean populate the database *with* your test cases?-->your
|
|
test cases also — again, within the same transaction.</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> (that is,
|
|
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>As you can see in the PetClinic application, the Spring
|
|
configuration is split across multiple files. <!--Where do we see this?-->As
|
|
is typical of large-scale applications, configuration locations are
|
|
often 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>HibernateTemplate</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> /
|
|
<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 id="testing-resources">
|
|
<title>Further Resources</title>
|
|
|
|
<para>Consult the following resources for more information about
|
|
testing:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><ulink url="http://www.junit.org/">JUnit</ulink>: The Spring
|
|
Framework's unit and integration test suite, written with JUnit 3.8.2
|
|
and JUnit 4.7 as the testing framework.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><ulink url="http://testng.org/">TestNG</ulink>: A testing
|
|
framework inspired by JUnit 3.8 with added support for Java 5
|
|
annotations, test groups, data-driven testing, distributed testing,
|
|
and so on.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><ulink
|
|
url="http://www.mockobjects.com/">MockObjects.com</ulink>: Web site
|
|
dedicated to mock objects, a technique for improving the design of
|
|
code within test-driven development.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><ulink url="http://en.wikipedia.org/wiki/Mock_Object">"Mock
|
|
Objects"</ulink>: Article in Wikipedia.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><ulink url="http://www.easymock.org/">EasyMock</ulink>: Used
|
|
extensively by the Spring Framework in its test suite.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><ulink url="http://www.jmock.org/">JMock</ulink>: Library that
|
|
supports test-driven development of Java code with mock
|
|
objects.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><ulink url="http://mockito.org/">Mockito</ulink>: Java mock
|
|
library based on the <ulink
|
|
url="http://xunitpatterns.com/Test%20Spy.html">test spy</ulink>
|
|
pattern.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><ulink url="http://dbunit.sourceforge.net/">DbUnit</ulink>:
|
|
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><ulink url="http://grinder.sourceforge.net/">Grinder</ulink>:
|
|
Java load testing framework.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
</chapter>
|