You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1810 lines
86 KiB
1810 lines
86 KiB
<?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 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 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, 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 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 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 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> |
|
|
|
<!--TODO Modify the following paragraph regarding 3.1's support for @Configuration classes.--> |
|
|
|
<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 suite), 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 — the TestContext framework can be configured to reload the |
|
configuration and rebuild 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>HibernateTitleRepository</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>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 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-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. Note, however, that you typically do |
|
not need to explicitly configure the loader since the default loader |
|
supports either resource <varname>locations</varname> or |
|
configuration <varname>classes</varname>.</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> |
|
|
|
<para>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> is |
|
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 |
|
via 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 |
|
via 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 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">@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>@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'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">@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>@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 or TestNG. 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, 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, and provides context management and caching |
|
support for the test instance for which it is responsible.</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>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 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 location. 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 |
|
explicitly configure 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, which is the default). A plain path, for example |
|
<literal>"context.xml"</literal>, will be treated as a classpath |
|
resource from the same package in which the test class is defined. A |
|
path starting with a slash is treated as a fully qualified classpath |
|
location, for example <literal>"/org/example/config.xml"</literal>. A |
|
path which represents a URL (i.e., a path prefixed with |
|
<literal>classpath:</literal>, <literal>file:</literal>, |
|
<literal>http:</literal>, etc.) will be used <emphasis>as |
|
is</emphasis>. 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(locations={"/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.</para> |
|
|
|
<para><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 shadow and effectively replace 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 suite), 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 — you can annotate your test class or test method with |
|
<interfacename>@DirtiesContext</interfacename> (assuming |
|
<classname>DirtiesContextTestExecutionListener</classname> has been |
|
configured, which is the default). This instructs Spring to reload the |
|
configuration 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 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 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 <emphasis |
|
role="bold">by type</emphasis></lineannotation> |
|
<emphasis role="bold">@Autowired</emphasis> |
|
private HibernateTitleRepository titleRepository; |
|
|
|
@Test |
|
public void loadTitle() { |
|
Title title = titleRepository.loadTitle(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 <emphasis |
|
role="bold">by type</emphasis></lineannotation> |
|
private HibernateTitleRepository titleRepository; |
|
|
|
<emphasis role="bold">@Autowired</emphasis> |
|
public void setTitleRepository(HibernateTitleRepository titleRepository) { |
|
this.titleRepository = titleRepository; |
|
} |
|
|
|
@Test |
|
public void loadTitle() { |
|
Title title = titleRepository.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>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-3.0.xsd"> |
|
|
|
<lineannotation><!-- this bean will be injected into the <classname>HibernateTitleRepositoryTests</classname> 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) { |
|
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).</para> |
|
</note> |
|
</section> |
|
|
|
<section 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 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-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 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 id="testcontext-support-classes"> |
|
<title>TestContext support classes</title> |
|
|
|
<section 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>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>@RunWith(SpringJUnit4ClassRunner.class)</interfacename>, |
|
<interfacename>@ContextConfiguration</interfacename>, |
|
<interfacename>@TestExecutionListeners</interfacename>, and so |
|
on.</para> |
|
</tip> |
|
</section> |
|
|
|
<section 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.8.2). 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 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>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.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 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>: |
|
<quote><emphasis>A programmer-oriented testing framework for |
|
Java</emphasis></quote>. Used by the Spring Framework in its test |
|
suite.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para><ulink url="http://testng.org/">TestNG</ulink>: 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><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>: 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><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>
|
|
|