replace XML usage of JndiObjectFactoryBean with <jee:jndi-lookup/>

git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@1401 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
Mark Pollack 2009-06-19 12:22:18 +00:00
parent 0dab269dba
commit 6b37493d2f
5 changed files with 1792 additions and 1737 deletions

File diff suppressed because it is too large Load Diff

View File

@ -198,7 +198,8 @@
<para>Destinations, like ConnectionFactories, are JMS administered <para>Destinations, like ConnectionFactories, are JMS administered
objects that can be stored and retrieved in JNDI. When configuring a objects that can be stored and retrieved in JNDI. When configuring a
Spring application context you can use the JNDI factory class Spring application context you can use the JNDI factory class
<classname>JndiObjectFactoryBean</classname> to perform dependency <classname>JndiObjectFactoryBean</classname> /
<literal>&lt;jee:jndi-lookup&gt;</literal> to perform dependency
injection on your object's references to JMS destinations. However, injection on your object's references to JMS destinations. However,
often this strategy is cumbersome if there are a large number of often this strategy is cumbersome if there are a large number of
destinations in the application or if there are advanced destination destinations in the application or if there are advanced destination

View File

@ -286,15 +286,14 @@ public class ProductDaoImpl implements ProductDao {
<programlisting language="xml">&lt;beans&gt; <programlisting language="xml">&lt;beans&gt;
&lt;bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean"&gt; &lt;jee:jndi-lookup id="myDataSource" jndi-name="java:comp/env/jdbc/myds"/&gt;
&lt;property name="jndiName" value="java:comp/env/jdbc/myds"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting> &lt;/beans&gt;</programlisting>
<para>You can also access a JNDI-located <para>You can also access a JNDI-located
<interfacename>SessionFactory</interfacename>, using Spring's <interfacename>SessionFactory</interfacename>, using Spring's
<classname>JndiObjectFactoryBean</classname> to retrieve and expose it. <classname>JndiObjectFactoryBean</classname> /
<literal>&lt;jee:jndi-lookup&gt;</literal> to retrieve and expose it.
However, that is typically not common outside of an EJB context.</para> However, that is typically not common outside of an EJB context.</para>
</section> </section>
@ -618,13 +617,9 @@ public class ProductDaoImpl implements ProductDao {
<programlisting language="xml">&lt;beans&gt; <programlisting language="xml">&lt;beans&gt;
&lt;bean id="myDataSource1" class="org.springframework.jndi.JndiObjectFactoryBean"&gt; &lt;jee:jndi-lookup id="dataSource1" jndi-name="java:comp/env/jdbc/myds1"/&gt;
&lt;property name="jndiName value="java:comp/env/jdbc/myds1"/&gt;
&lt;/bean&gt;
&lt;bean id="myDataSource2" class="org.springframework.jndi.JndiObjectFactoryBean"&gt; &lt;jee:jndi-lookup id="dataSource2" jndi-name="java:comp/env/jdbc/myds2"/&gt;
&lt;property name="jndiName" value="java:comp/env/jdbc/myds2"/&gt;
&lt;/bean&gt;
&lt;bean id="mySessionFactory1" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&gt; &lt;bean id="mySessionFactory1" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&gt;
&lt;property name="dataSource" ref="myDataSource1"/&gt; &lt;property name="dataSource" ref="myDataSource1"/&gt;
@ -795,7 +790,8 @@ public class ProductDaoImpl implements ProductDao {
<para>If in your application context you are already directly <para>If in your application context you are already directly
obtaining the JTA obtaining the JTA
<interfacename>PlatformTransactionManager</interfacename> object <interfacename>PlatformTransactionManager</interfacename> object
(presumably from JNDI via <literal>JndiObjectFactoryBean</literal>) (presumably from JNDI via
<literal>JndiObjectFactoryBean/<literal>&lt;jee:jndi-lookup&gt;</literal></literal>)
and feeding it for example to Spring's and feeding it for example to Spring's
<classname>JtaTransactionManager</classname>, then the easiest way <classname>JtaTransactionManager</classname>, then the easiest way
is to simply specify a reference to this as the value of is to simply specify a reference to this as the value of
@ -953,12 +949,13 @@ public class ProductDaoImpl implements ProductDao {
<para>A JDO <interfacename>PersistenceManagerFactory</interfacename> can <para>A JDO <interfacename>PersistenceManagerFactory</interfacename> can
also be set up in the JNDI environment of a J2EE application server, also be set up in the JNDI environment of a J2EE application server,
usually through the JCA connector provided by the particular JDO usually through the JCA connector provided by the particular JDO
implementation. Spring's standard implementation. Spring's standard <literal>JndiObjectFactoryBean /
<literal>JndiObjectFactoryBean</literal> can be used to retrieve and <literal>&lt;jee:jndi-lookup&gt;</literal></literal> can be used to
expose such a <interfacename>PersistenceManagerFactory</interfacename>. retrieve and expose such a
However, outside an EJB context, there is often no compelling benefit in <interfacename>PersistenceManagerFactory</interfacename>. However,
holding the <interfacename>PersistenceManagerFactory</interfacename> in outside an EJB context, there is often no compelling benefit in holding
JNDI: only choose such setup for a good reason. See "container resources the <interfacename>PersistenceManagerFactory</interfacename> in JNDI:
only choose such setup for a good reason. See "container resources
versus local resources" in the Hibernate section for a discussion; the versus local resources" in the Hibernate section for a discussion; the
arguments there apply to JDO as well.</para> arguments there apply to JDO as well.</para>
</section> </section>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="testing"> <chapter id="testing">
<title>Testing</title> <title>Testing</title>
@ -22,8 +21,8 @@
<para>One of the main benefits of Dependency Injection is that your code <para>One of the main benefits of Dependency Injection is that your code
should really depend far less on the container than in traditional J2EE should really depend far less on the container than in traditional J2EE
development. The POJOs that make up your application should be testable development. The POJOs that make up your application should be testable in
in JUnit or TestNG tests, with objects simply instantiated using the JUnit or TestNG tests, with objects simply instantiated using the
<literal>new</literal> operator, <emphasis>without Spring or any other <literal>new</literal> operator, <emphasis>without Spring or any other
container</emphasis>. You can use <link linkend="mock-objects">mock container</emphasis>. You can use <link linkend="mock-objects">mock
objects</link> (in conjunction with many other valuable testing objects</link> (in conjunction with many other valuable testing
@ -120,21 +119,20 @@
<title>Spring MVC</title> <title>Spring MVC</title>
<para>The <literal>org.springframework.test.web</literal> package <para>The <literal>org.springframework.test.web</literal> package
contains <classname>ModelAndViewAssert</classname>, which can be contains <classname>ModelAndViewAssert</classname>, which can be used
used in combination with any testing framework (e.g., JUnit 4+, in combination with any testing framework (e.g., JUnit 4+, TestNG,
TestNG, etc.) for unit tests dealing with Spring MVC etc.) for unit tests dealing with Spring MVC
<classname>ModelAndView</classname> objects.</para> <classname>ModelAndView</classname> objects.</para>
<tip> <tip>
<title>Unit testing Spring MVC Controllers</title> <title>Unit testing Spring MVC Controllers</title>
<para>
To test your Spring MVC <literal>Controller</literal>s, <para>To test your Spring MVC <literal>Controller</literal>s, use
use <classname>ModelAndViewAssert</classname> combined with <classname>ModelAndViewAssert</classname> combined with
<literal>MockHttpServletRequest</literal>, <literal>MockHttpServletRequest</literal>,
<literal>MockHttpSession</literal>, etc. from the <link <literal>MockHttpSession</literal>, etc. from the <link
linkend="mock-objects-servlet"><literal>org.springframework.mock.web</literal></link> linkend="mock-objects-servlet"><literal>org.springframework.mock.web</literal></link>
package. package.</para>
</para>
</tip> </tip>
</section> </section>
</section> </section>
@ -165,44 +163,43 @@
</itemizedlist> </itemizedlist>
<para>The Spring Framework provides first class support for integration <para>The Spring Framework provides first class support for integration
testing in the <filename class="libraryfile">org.springframework.test-VERSION.jar</filename> testing in the <filename
library (where <literal>VERSION</literal> is the release version). In this library, class="libraryfile">org.springframework.test-VERSION.jar</filename>
you will find the <literal>org.springframework.test</literal> package library (where <literal>VERSION</literal> is the release version). In
which contains valuable classes for integration testing using a Spring this library, you will find the
container, while at the same time not being reliant on an application <literal>org.springframework.test</literal> package which contains
server or other deployment environment. Such tests will be slower to run valuable classes for integration testing using a Spring container, while
than unit tests but much faster to run than the equivalent Cactus tests at the same time not being reliant on an application server or other
or remote tests relying on deployment to an application server.</para> deployment environment. Such tests will be slower to run than unit tests
but much faster to run than the equivalent Cactus tests or remote tests
relying on deployment to an application server.</para>
<para> <para>Since Spring 2.5, unit and integration testing support is provided
Since Spring 2.5, unit and integration testing support is provided
in the form of the annotation-driven <link in the form of the annotation-driven <link
linkend="testcontext-framework">Spring TestContext Framework</link>. linkend="testcontext-framework">Spring TestContext Framework</link>. The
The TestContext Framework is agnostic of the actual testing framework TestContext Framework is agnostic of the actual testing framework in
in use, thus allowing use, thus allowing instrumentation of tests in various environments
instrumentation of tests in various environments including JUnit 3.8, including JUnit 3.8, JUnit 4.5, TestNG, etc.</para>
JUnit 4.5, TestNG, etc.
</para>
<note> <note>
<title>Legacy JUnit 3.8 class hierarchy is deprecated</title> <title>Legacy JUnit 3.8 class hierarchy is deprecated</title>
<para>
As of Spring 3.0, the legacy JUnit 3.8 base class hierarchy (e.g., <para>As of Spring 3.0, the legacy JUnit 3.8 base class hierarchy
(e.g.,
<classname>AbstractDependencyInjectionSpringContextTests</classname>, <classname>AbstractDependencyInjectionSpringContextTests</classname>,
<classname>AbstractTransactionalDataSourceSpringContextTests</classname>, <classname>AbstractTransactionalDataSourceSpringContextTests</classname>,
etc.) is officially deprecated and will be removed in a later release. etc.) is officially deprecated and will be removed in a later release.
Thus any code which depends on the legacy JUnit 3.8 support should be Thus any code which depends on the legacy JUnit 3.8 support should be
migrated to the <link migrated to the <link linkend="testcontext-framework">Spring
linkend="testcontext-framework">Spring TestContext Framework</link>. TestContext Framework</link>.</para>
</para>
</note> </note>
</section> </section>
<section id="integration-testing-goals"> <section id="integration-testing-goals">
<title>Goals</title> <title>Goals</title>
<para>The following bullet points highlight the fundamental goals of Spring's <para>The following bullet points highlight the fundamental goals of
integration testing support:</para> Spring's integration testing support:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -227,32 +224,31 @@
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>In the next few sections each of the above goals is discussed <para>In the next few sections each of the above goals is discussed in
in greater detail, and at the end of each section you will find a direct greater detail, and at the end of each section you will find a direct
link to implementation and configuration details pertaining to that link to implementation and configuration details pertaining to that
particular goal.</para> particular goal.</para>
<section id="testing-ctx-management"> <section id="testing-ctx-management">
<title>Context management and caching</title> <title>Context management and caching</title>
<para>The Spring TestContext Framework provides consistent <para>The Spring TestContext Framework provides consistent loading of
loading of Spring <classname>ApplicationContext</classname>s and Spring <classname>ApplicationContext</classname>s and caching of those
caching of those contexts. Support for the caching of loaded contexts contexts. Support for the caching of loaded contexts is important,
is important, because if you are working on a large project, startup because if you are working on a large project, startup time may become
time may become an issue - not because of the overhead of Spring an issue - not because of the overhead of Spring itself, but because
itself, but because the objects instantiated by the Spring container the objects instantiated by the Spring container will themselves take
will themselves take time to instantiate. For example, a project with time to instantiate. For example, a project with 50-100 Hibernate
50-100 Hibernate mapping files might take 10-20 seconds to load the mapping files might take 10-20 seconds to load the mapping files, and
mapping files, and incurring that cost before running every single incurring that cost before running every single test in every single
test in every single test fixture will lead to slower overall test test fixture will lead to slower overall test runs that could reduce
runs that could reduce productivity.</para> productivity.</para>
<para>Test classes provide an array containing the <para>Test classes provide an array containing the resource locations
resource locations of XML configuration metadata - typically on the of XML configuration metadata - typically on the classpath - used to
classpath - used to configure the application. This will be the same, configure the application. This will be the same, or nearly the same,
or nearly the same, as the list of configuration locations specified as the list of configuration locations specified in
in <literal>web.xml</literal> or other deployment <literal>web.xml</literal> or other deployment configuration.</para>
configuration.</para>
<para>By default, once loaded, the configured <para>By default, once loaded, the configured
<interfacename>ApplicationContext</interfacename> will be reused for <interfacename>ApplicationContext</interfacename> will be reused for
@ -264,22 +260,21 @@
a mechanism to cause the test fixture to reload the configurations and a mechanism to cause the test fixture to reload the configurations and
rebuild the application context before executing the next test.</para> rebuild the application context before executing the next test.</para>
<para> <para>See: context management and caching with the <link
See: context management and caching with the linkend="testcontext-ctx-management">TestContext
<link linkend="testcontext-ctx-management">TestContext Framework</link>. Framework</link>.</para>
</para>
</section> </section>
<section id="testing-fixture-di"> <section id="testing-fixture-di">
<title>Dependency Injection of test fixtures</title> <title>Dependency Injection of test fixtures</title>
<para>When the TestContext framework loads your <para>When the TestContext framework loads your application context,
application context, it can optionally configure instances of your it can optionally configure instances of your test classes via
test classes via Dependency Injection. This provides a convenient Dependency Injection. This provides a convenient mechanism for setting
mechanism for setting up test fixtures using pre-configured beans from up test fixtures using pre-configured beans from your application
your application context. A strong benefit here is that you can reuse context. A strong benefit here is that you can reuse application
application contexts across various testing scenarios (e.g., for contexts across various testing scenarios (e.g., for configuring
configuring Spring-managed object graphs, transactional proxies, Spring-managed object graphs, transactional proxies,
<classname>DataSource</classname>s, etc.), thus avoiding the need to <classname>DataSource</classname>s, etc.), thus avoiding the need to
duplicate complex test fixture set up for individual test duplicate complex test fixture set up for individual test
cases.</para> cases.</para>
@ -311,10 +306,8 @@
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para> <para>See: dependency injection of test fixtures with the <link
See: dependency injection of test fixtures with the linkend="testcontext-fixture-di">TestContext Framework</link>.</para>
<link linkend="testcontext-fixture-di">TestContext Framework</link>.
</para>
</section> </section>
<section id="testing-tx"> <section id="testing-tx">
@ -323,47 +316,42 @@
<para>One common issue in tests that access a real database is their <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 affect on the state of the persistence store. Even when you're using a
development database, changes to the state may affect future tests. development database, changes to the state may affect future tests.
Also, many operations - such as inserting or modifying persistent Also, many operations - such as inserting or modifying persistent data
data - cannot be performed (or verified) outside a transaction.</para> - cannot be performed (or verified) outside a transaction.</para>
<para>The TestContext framework addresses this issue. By default, <para>The TestContext framework addresses this issue. By default, the
the framework will create and roll back a transaction for each framework will create and roll back a transaction for each test. You
test. You simply write code that can assume the existence of a simply write code that can assume the existence of a transaction. If
transaction. If you call transactionally proxied objects in your you call transactionally proxied objects in your tests, they will
tests, they will behave correctly, according to their transactional behave correctly, according to their transactional semantics. In
semantics. In addition, if test methods delete the contents of addition, if test methods delete the contents of selected tables while
selected tables while running within a transaction, the transaction running within a transaction, the transaction will roll back by
will roll back by default, and the database will return to its state default, and the database will return to its state prior to execution
prior to execution of the test. Transactional support is provided to of the test. Transactional support is provided to your test class via
your test class via a a <classname>PlatformTransactionManager</classname> bean defined in
<classname>PlatformTransactionManager</classname> bean defined in the the test's application context.</para>
test's application context.</para>
<para>If you want a transaction to commit - unusual, but occasionally <para>If you want a transaction to commit - unusual, but occasionally
useful when you want a particular test to populate or modify the useful when you want a particular test to populate or modify the
database - the TestContext framework can be database - the TestContext framework can be instructed to cause the
instructed to cause the transaction to commit instead of roll back transaction to commit instead of roll back via the <link
via the linkend="integration-testing-annotations"><interfacename>@TransactionConfiguration</interfacename></link>
<link linkend="integration-testing-annotations"><interfacename>@TransactionConfiguration</interfacename></link> and <link
and linkend="integration-testing-annotations"><interfacename>@Rollback</interfacename></link>
<link linkend="integration-testing-annotations"><interfacename>@Rollback</interfacename></link>
annotations.</para> annotations.</para>
<para> <para>See: transaction management with the <link
See: transaction management with the linkend="testcontext-tx">TestContext Framework</link>.</para>
<link linkend="testcontext-tx">TestContext Framework</link>.
</para>
</section> </section>
<section id="testing-support-classes"> <section id="testing-support-classes">
<title>Integration testing support classes</title> <title>Integration testing support classes</title>
<para>The Spring TestContext Framework provides <para>The Spring TestContext Framework provides several
several <literal>abstract</literal> support classes that can simplify <literal>abstract</literal> support classes that can simplify writing
writing integration tests. These base test classes provide well integration tests. These base test classes provide well defined hooks
defined hooks into the testing framework as well as convenient into the testing framework as well as convenient instance variables
instance variables and methods, allowing access to such things and methods, allowing access to such things as:</para>
as:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -373,10 +361,10 @@
</listitem> </listitem>
<listitem> <listitem>
<para>A <classname>SimpleJdbcTemplate</classname>: useful for querying to <para>A <classname>SimpleJdbcTemplate</classname>: useful for
confirm state. For example, you might query before and after querying to confirm state. For example, you might query before and
testing application code that creates an object and persists it after testing application code that creates an object and persists
using an ORM tool, to verify that the data appears in the it using an ORM tool, to verify that the data appears in the
database. (Spring will ensure that the query runs in the scope of database. (Spring will ensure that the query runs in the scope of
the same transaction.) You will need to tell your ORM tool to the same transaction.) You will need to tell your ORM tool to
'flush' its changes for this to work correctly, for example using 'flush' its changes for this to work correctly, for example using
@ -385,16 +373,14 @@
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para> <para>In addition, you may find it desirable to provide your own
In addition, you may find it desirable to provide your own custom, custom, application-wide superclass for integration tests that
application-wide superclass for integration tests that provides provides further useful instance variables and methods specific to
further useful instance variables and your project.</para>
methods specific to your project.</para>
<para> <para>See: support classes for the <link
See: support classes for the linkend="testcontext-support-classes">TestContext
<link linkend="testcontext-support-classes">TestContext Framework</link>. Framework</link>.</para>
</para>
</section> </section>
</section> </section>
@ -420,19 +406,18 @@
<!-- =============================================================== --> <!-- =============================================================== -->
<para>The Spring Framework provides the following set of <para>The Spring Framework provides the following set of
<emphasis>Spring-specific</emphasis> annotations that you <emphasis>Spring-specific</emphasis> annotations that you can use in
can use in your unit and integration tests in conjunction with the your unit and integration tests in conjunction with the TestContext
TestContext framework. Refer to the respective JavaDoc for framework. Refer to the respective JavaDoc for further information,
further information, including default attribute values, etc.</para> including default attribute values, etc.</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para><emphasis <para><emphasis
role="bold"><interfacename>@ContextConfiguration</interfacename></emphasis></para> role="bold"><interfacename>@ContextConfiguration</interfacename></emphasis></para>
<para>Defines class-level metadata which is used to determine how <para>Defines class-level metadata which is used to determine how to
to load and configure an load and configure an
<interfacename>ApplicationContext</interfacename>. Specifically, <interfacename>ApplicationContext</interfacename>. Specifically,
@ContextConfiguration defines the application context resource @ContextConfiguration defines the application context resource
<literal>locations</literal> to load as well as the <literal>locations</literal> to load as well as the
@ -468,6 +453,7 @@ public void testProcessWhichDirtiesAppCtx() {
<lineannotation>// some logic that results in the Spring container being dirtied</lineannotation> <lineannotation>// some logic that results in the Spring container being dirtied</lineannotation>
}</programlisting> }</programlisting>
</listitem> </listitem>
<listitem> <listitem>
<para><emphasis <para><emphasis
role="bold"><interfacename>@TestExecutionListeners</interfacename></emphasis></para> role="bold"><interfacename>@TestExecutionListeners</interfacename></emphasis></para>
@ -487,8 +473,7 @@ public class CustomTestExecutionListenerTests {
<para>Note: <interfacename>@TestExecutionListeners</interfacename> <para>Note: <interfacename>@TestExecutionListeners</interfacename>
provides support for <emphasis>inherited</emphasis> listeners by provides support for <emphasis>inherited</emphasis> listeners by
default. See the JavaDoc for an example and further default. See the JavaDoc for an example and further details.</para>
details.</para>
</listitem> </listitem>
<listitem> <listitem>
@ -497,12 +482,12 @@ public class CustomTestExecutionListenerTests {
<para>Defines class-level metadata for configuring transactional <para>Defines class-level metadata for configuring transactional
tests. Specifically, the bean name of the tests. Specifically, the bean name of the
<interfacename>PlatformTransactionManager</interfacename> that is <interfacename>PlatformTransactionManager</interfacename> that is to
to be used to drive transactions can be explicitly configured if be used to drive transactions can be explicitly configured if the
the bean name of the desired PlatformTransactionManager is not bean name of the desired PlatformTransactionManager is not
"transactionManager". In addition, the "transactionManager". In addition, the
<literal>defaultRollback</literal> flag can optionally be changed <literal>defaultRollback</literal> flag can optionally be changed to
to <literal>false</literal>. Typically, <literal>false</literal>. Typically,
<interfacename>@TransactionConfiguration</interfacename> will be <interfacename>@TransactionConfiguration</interfacename> will be
used in conjunction with used in conjunction with
<interfacename>@ContextConfiguration</interfacename>.</para> <interfacename>@ContextConfiguration</interfacename>.</para>
@ -537,9 +522,9 @@ public void testProcessWithoutRollback() {
role="bold"><interfacename>@BeforeTransaction</interfacename></emphasis></para> role="bold"><interfacename>@BeforeTransaction</interfacename></emphasis></para>
<para>Indicates that the annotated <literal>public void</literal> <para>Indicates that the annotated <literal>public void</literal>
method should be executed <emphasis>before</emphasis> a method should be executed <emphasis>before</emphasis> a transaction
transaction is started for test methods configured to run within a is started for test methods configured to run within a transaction
transaction via the <interfacename>@Transactional</interfacename> via the <interfacename>@Transactional</interfacename>
annotation.</para> annotation.</para>
<programlisting language="java">@BeforeTransaction <programlisting language="java">@BeforeTransaction
@ -578,18 +563,16 @@ public void testProcessWithoutTransaction() {
<lineannotation>// ...</lineannotation> <lineannotation>// ...</lineannotation>
}</programlisting> }</programlisting>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<!-- =============================================================== --> <!-- =============================================================== -->
<para>The following annotations are <emphasis>only</emphasis> <para>The following annotations are <emphasis>only</emphasis> supported
supported when used in conjunction with JUnit (i.e., with the <link when used in conjunction with JUnit (i.e., with the <link
linkend="testcontext-junit4-runner">SpringJUnit4ClassRunner</link> or linkend="testcontext-junit4-runner">SpringJUnit4ClassRunner</link> or
the <link linkend="testcontext-support-classes-junit38">JUnit the <link linkend="testcontext-support-classes-junit38">JUnit 3.8</link>
3.8</link> and <link and <link linkend="testcontext-support-classes-junit45">JUnit 4.5</link>
linkend="testcontext-support-classes-junit45">JUnit 4.5</link> support support classes.</para>
classes.</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -662,8 +645,8 @@ public void testProcessRainyDayScenario() {
conjunction with JUnit 4's conjunction with JUnit 4's
<interfacename>@Test(expected=...)</interfacename> configuration <interfacename>@Test(expected=...)</interfacename> configuration
would lead to an unresolvable conflict. Developers must therefore would lead to an unresolvable conflict. Developers must therefore
choose one or the other when integrating with JUnit 4, in which choose one or the other when integrating with JUnit 4, in which case
case it is generally preferable to use the explicit JUnit 4 it is generally preferable to use the explicit JUnit 4
configuration.</para> configuration.</para>
</listitem> </listitem>
@ -687,19 +670,19 @@ public void testProcessWithOneSecondTimeout() {
<lineannotation>// some logic that should not take longer than 1 second to execute</lineannotation> <lineannotation>// some logic that should not take longer than 1 second to execute</lineannotation>
}</programlisting> }</programlisting>
<para>Spring's <interfacename>@Timed</interfacename> annotation <para>Spring's <interfacename>@Timed</interfacename> annotation has
has different semantics than JUnit 4's different semantics than JUnit 4's
<interfacename>@Test(timeout=...)</interfacename> support. <interfacename>@Test(timeout=...)</interfacename> support.
Specifically, due to the manner in which JUnit 4 handles test Specifically, due to the manner in which JUnit 4 handles test
execution timeouts (i.e., by executing the test method in a execution timeouts (i.e., by executing the test method in a separate
separate <classname>Thread</classname>), <classname>Thread</classname>),
<interfacename>@Test(timeout=...)</interfacename> applies to <interfacename>@Test(timeout=...)</interfacename> applies to
<emphasis>each iteration</emphasis> in the case of repetitions <emphasis>each iteration</emphasis> in the case of repetitions and
and preemptively fails the test if the test takes too long. preemptively fails the test if the test takes too long. Spring's
Spring's <interfacename>@Timed</interfacename>, on the other hand, <interfacename>@Timed</interfacename>, on the other hand, times the
times the <emphasis>total</emphasis> test execution time <emphasis>total</emphasis> test execution time (including all
(including all repetitions) and does not preemptively fail the test repetitions) and does not preemptively fail the test but rather
but rather waits for the test to actually complete before failing.</para> waits for the test to actually complete before failing.</para>
</listitem> </listitem>
<listitem> <listitem>
@ -721,16 +704,13 @@ public void testProcessRepeatedly() {
<lineannotation>// ...</lineannotation> <lineannotation>// ...</lineannotation>
}</programlisting> }</programlisting>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<!-- =============================================================== --> <!-- =============================================================== -->
<para> <para>The following non-test-specific annotations are supported with
The following non-test-specific annotations are supported with standard semantics for all configurations of the Spring TestContext
standard semantics for all Framework.</para>
configurations of the Spring TestContext Framework.
</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -745,8 +725,8 @@ public void testProcessRepeatedly() {
<listitem> <listitem>
<para><emphasis <para><emphasis
role="bold"><interfacename>@Resource</interfacename></emphasis> (javax.annotation) role="bold"><interfacename>@Resource</interfacename></emphasis>
<emphasis>if JSR-250 is present</emphasis></para> (javax.annotation) <emphasis>if JSR-250 is present</emphasis></para>
</listitem> </listitem>
<listitem> <listitem>
@ -895,13 +875,13 @@ public void testProcessRepeatedly() {
<tip> <tip>
<title>@Autowired ApplicationContext</title> <title>@Autowired ApplicationContext</title>
<para>
As an alternative to implementing the <para>As an alternative to implementing the
<interfacename>ApplicationContextAware</interfacename> interface, <interfacename>ApplicationContextAware</interfacename> interface,
your test class can have its application context injected via the your test class can have its application context injected via the
<interfacename>@Autowired</interfacename> annotation on either a <interfacename>@Autowired</interfacename> annotation on either a
field or setter method, for example: field or setter method, for example:</para>
</para>
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class) <programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration @ContextConfiguration
public class MyTest { public class MyTest {
@ -912,20 +892,20 @@ public class MyTest {
}</programlisting> }</programlisting>
</tip> </tip>
<para>In contrast to the now deprecated JUnit 3.8 legacy class hierarchy, <para>In contrast to the now deprecated JUnit 3.8 legacy class
test classes which use the TestContext framework do not need to override hierarchy, test classes which use the TestContext framework do not
any <literal>protected</literal> instance methods to configure their need to override any <literal>protected</literal> instance methods to
application context. Rather, configuration is achieved merely by configure their application context. Rather, configuration is achieved
declaring the <interfacename>@ContextConfiguration</interfacename> merely by declaring the
annotation at the class level. If your test class does not explicitly <interfacename>@ContextConfiguration</interfacename> annotation at the
declare any application context resource <literal>locations</literal>, class level. If your test class does not explicitly declare any
the configured <interfacename>ContextLoader</interfacename> will application context resource <literal>locations</literal>, the
determine how and whether or not to load a context from a default set configured <interfacename>ContextLoader</interfacename> will determine
of locations. For example, how and whether or not to load a context from a default set of
<classname>GenericXmlContextLoader</classname> - which is the default locations. For example, <classname>GenericXmlContextLoader</classname>
<interfacename>ContextLoader</interfacename> - will generate a default - which is the default <interfacename>ContextLoader</interfacename> -
location based on the name of the test class. If your class is named will generate a default location based on the name of the test class.
<literal>com.example.MyTest</literal>, If your class is named <literal>com.example.MyTest</literal>,
<classname>GenericXmlContextLoader</classname> will load your <classname>GenericXmlContextLoader</classname> will load your
application context from application context from
<literal>"classpath:/com/example/MyTest-context.xml"</literal>.</para> <literal>"classpath:/com/example/MyTest-context.xml"</literal>.</para>
@ -960,16 +940,16 @@ public class MyTest {
<lineannotation>// class body...</lineannotation> <lineannotation>// class body...</lineannotation>
}</programlisting> }</programlisting>
<para><interfacename>@ContextConfiguration</interfacename> supports <para><interfacename>@ContextConfiguration</interfacename> supports an
an alias for the <literal>locations</literal> attribute via the alias for the <literal>locations</literal> attribute via the standard
standard <literal>value</literal> attribute. Thus, if you do not need <literal>value</literal> attribute. Thus, if you do not need to
to configure a custom <interfacename>ContextLoader</interfacename>, you configure a custom <interfacename>ContextLoader</interfacename>, you
can omit the declaration of the <literal>locations</literal> attribute can omit the declaration of the <literal>locations</literal> attribute
name and declare the resource locations using the shorthand format name and declare the resource locations using the shorthand format
demonstrated in the following example. demonstrated in the following example.
<interfacename>@ContextConfiguration</interfacename> also <interfacename>@ContextConfiguration</interfacename> also supports a
supports a boolean <literal>inheritLocations</literal> attribute which boolean <literal>inheritLocations</literal> attribute which denotes
denotes whether or not resource locations from superclasses should be whether or not resource locations from superclasses should be
<emphasis>inherited</emphasis>. The default value is <emphasis>inherited</emphasis>. The default value is
<literal>true</literal>, which means that an annotated class will <literal>true</literal>, which means that an annotated class will
<emphasis>inherit</emphasis> the resource locations defined by an <emphasis>inherit</emphasis> the resource locations defined by an
@ -1037,8 +1017,8 @@ public class ExtendedTest extends BaseTest {
consistency with the annotation support introduced in Spring 2.5, you consistency with the annotation support introduced in Spring 2.5, you
may choose either Spring's <interfacename>@Autowired</interfacename> may choose either Spring's <interfacename>@Autowired</interfacename>
annotation or the <interfacename>@Resource</interfacename> annotation annotation or the <interfacename>@Resource</interfacename> annotation
from JSR 250. The semantics for both are consistent throughout the Spring from JSR 250. The semantics for both are consistent throughout the
Framework. For example, if you prefer <link Spring Framework. For example, if you prefer <link
linkend="beans-factory-autowire"><emphasis>autowiring by linkend="beans-factory-autowire"><emphasis>autowiring by
type</emphasis></link>, annotate your setter methods or fields with type</emphasis></link>, annotate your setter methods or fields with
<interfacename>@Autowired</interfacename>. On the other hand, if you <interfacename>@Autowired</interfacename>. On the other hand, if you
@ -1063,9 +1043,8 @@ public class ExtendedTest extends BaseTest {
<classname>ApplicationContext</classname>, you can perform an explicit <classname>ApplicationContext</classname>, you can perform an explicit
lookup using (for example) a call to lookup using (for example) a call to
<methodname>applicationContext.getBean("titleDao")</methodname>. A <methodname>applicationContext.getBean("titleDao")</methodname>. A
third option is to use <interfacename>@Autowired</interfacename> third option is to use <interfacename>@Autowired</interfacename> in
in conjunction with <interfacename>@Qualifier</interfacename>. conjunction with <interfacename>@Qualifier</interfacename>.</para>
</para>
<para>If you don't want dependency injection applied to your test <para>If you don't want dependency injection applied to your test
instances, simply don't annotate any fields or setter methods with instances, simply don't annotate any fields or setter methods with
@ -1079,14 +1058,14 @@ public class ExtendedTest extends BaseTest {
<para>Consider the scenario where we have a class, <para>Consider the scenario where we have a class,
<classname>HibernateTitleDao</classname> (as outlined in the <link <classname>HibernateTitleDao</classname> (as outlined in the <link
linkend="testing-fixture-di">Goals</link> section). First, linkend="testing-fixture-di">Goals</link> section). First, let's look
let's look at a JUnit 4.5 based implementation of the test class at a JUnit 4.5 based implementation of the test class itself which
itself which uses <interfacename>@Autowired</interfacename> for field uses <interfacename>@Autowired</interfacename> for field injection (we
injection (we will look at the application context configuration after will look at the application context configuration after all sample
all sample code listings). <emphasis>Note: The dependency injection code listings). <emphasis>Note: The dependency injection behavior in
behavior in the following code listings is not in any way specific to the following code listings is not in any way specific to JUnit 4.5.
JUnit 4.5. The same DI techniques can be used in conjunction with any The same DI techniques can be used in conjunction with any testing
testing framework.</emphasis></para> framework.</emphasis></para>
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class) <programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
<lineannotation>// specifies the Spring configuration to load for this test fixture</lineannotation> <lineannotation>// specifies the Spring configuration to load for this test fixture</lineannotation>
@ -1200,12 +1179,14 @@ public final class HibernateTitleDaoTests {
&lt;/beans&gt;</programlisting> &lt;/beans&gt;</programlisting>
<note> <note>
<para>If you are extending from a Spring-provided test base class that happens <para>If you are extending from a Spring-provided test base class
to use <interfacename>@Autowired</interfacename> on one of its setters methods, that happens to use <interfacename>@Autowired</interfacename> on one
you might have multiple beans of the affected type defined in your application context: of its setters methods, you might have multiple beans of the
e.g. multiple <interfacename>DataSource</interfacename> beans. In such a case, affected type defined in your application context: e.g. multiple
you may override the setter and use the <interfacename>@Qualifier</interfacename> <interfacename>DataSource</interfacename> beans. In such a case, you
annotation to indicate a specific target bean as follows:</para> may override the setter and use the
<interfacename>@Qualifier</interfacename> annotation to indicate a
specific target bean as follows:</para>
<programlisting language="java">... <programlisting language="java">...
@Override @Autowired @Override @Autowired
@ -1215,22 +1196,23 @@ public final class HibernateTitleDaoTests {
...</programlisting> ...</programlisting>
<para>The specified qualifier value indicates the specific <para>The specified qualifier value indicates the specific
<interfacename>DataSource</interfacename> bean to inject, <interfacename>DataSource</interfacename> bean to inject, narrowing
narrowing the set of type matches to a specific bean. the set of type matches to a specific bean. Its value is matched
Its value is matched against <literal>&lt;qualifier&gt;</literal> against <literal>&lt;qualifier&gt;</literal> declarations within the
declarations within the corresponding <literal>&lt;bean&gt;</literal> corresponding <literal>&lt;bean&gt;</literal> definitions. The bean
definitions. The bean name is used as a fallback qualifier value, name is used as a fallback qualifier value, so you may effectively
so you may effectively also point to a specific bean by name there also point to a specific bean by name there (as shown above,
(as shown above, assuming that "myDataSource" is the bean id). assuming that "myDataSource" is the bean id). If there is only one
If there is only one <interfacename>DataSource</interfacename> bean <interfacename>DataSource</interfacename> bean to begin with, then
to begin with, then the qualifier will simply not have any effect the qualifier will simply not have any effect - independent from the
- independent from the bean name of that single matching bean.</para> bean name of that single matching bean.</para>
<para>Alternatively, consider using the <interfacename>@Resource</interfacename> <para>Alternatively, consider using the
annotation on such an overridden setter methods, defining the <interfacename>@Resource</interfacename> annotation on such an
target bean name explicitly - with no type matching semantics. overridden setter methods, defining the target bean name explicitly
Note that this always points to a bean with that specific name, - with no type matching semantics. Note that this always points to a
no matter whether there is one or more beans of the given type.</para> bean with that specific name, no matter whether there is one or more
beans of the given type.</para>
<programlisting language="java">... <programlisting language="java">...
@Override <emphasis role="bold">@Resource("myDataSource")</emphasis> @Override <emphasis role="bold">@Resource("myDataSource")</emphasis>
@ -1263,8 +1245,8 @@ public final class HibernateTitleDaoTests {
<para>For class-level transaction configuration (i.e., setting the <para>For class-level transaction configuration (i.e., setting the
bean name for the transaction manager and the default rollback flag), bean name for the transaction manager and the default rollback flag),
see the <interfacename>@TransactionConfiguration</interfacename> entry see the <interfacename>@TransactionConfiguration</interfacename> entry
in the <link linkend="integration-testing-annotations">annotation support</link> in the <link linkend="integration-testing-annotations">annotation
section.</para> support</link> section.</para>
<para>There are several options for configuring transactions for <para>There are several options for configuring transactions for
individual test methods. If transactions are not enabled for the individual test methods. If transactions are not enabled for the
@ -1318,9 +1300,9 @@ public final class HibernateTitleDaoTests {
<para>The following JUnit 4 based example displays a fictitious <para>The following JUnit 4 based example displays a fictitious
integration testing scenario highlighting several of the integration testing scenario highlighting several of the
transaction-related annotations. Consult the <link transaction-related annotations. Consult the <link
linkend="integration-testing-annotations">annotation linkend="integration-testing-annotations">annotation support</link>
support</link> section of the reference manual for further information section of the reference manual for further information and
and configuration examples.</para> configuration examples.</para>
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class) <programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration @ContextConfiguration
@ -1635,7 +1617,6 @@ public class SimpleTest {
</section> </section>
<!-- ================================================================= --> <!-- ================================================================= -->
</section> </section>
<!-- === PetClinic Example ================================================= --> <!-- === PetClinic Example ================================================= -->
@ -1756,7 +1737,8 @@ public class HibernateClinicTests extends AbstractClinicTests { }
pooling and transaction infrastructure. If you are deploying to a pooling and transaction infrastructure. If you are deploying to a
full-blown application server, you will probably use its connection pool full-blown application server, you will probably use its connection pool
(available through JNDI) and JTA implementation. Thus in production you (available through JNDI) and JTA implementation. Thus in production you
will use a <classname>JndiObjectFactoryBean</classname> for the will use a <classname>JndiObjectFactoryBean</classname> /
<literal>&lt;jee:jndi-lookup&gt;</literal> for the
<classname>DataSource</classname> and <classname>DataSource</classname> and
<classname>JtaTransactionManager</classname>. JNDI and JTA will not be <classname>JtaTransactionManager</classname>. JNDI and JTA will not be
available in out-of-container integration tests, so you should use a available in out-of-container integration tests, so you should use a
@ -1777,56 +1759,57 @@ public class HibernateClinicTests extends AbstractClinicTests { }
<section id="testing-resources"> <section id="testing-resources">
<title>Further Resources</title> <title>Further Resources</title>
<para>This section contains links to further resources about testing in general.</para> <para>This section contains links to further resources about testing in
general.</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para><ulink url="http://www.junit.org/">JUnit</ulink>: <para><ulink url="http://www.junit.org/">JUnit</ulink>: the Spring
the Spring Framework's unit and integration test suite is written using Framework's unit and integration test suite is written using JUnit 3.8
JUnit 3.8 and JUnit 4.5 as the testing framework.</para> and JUnit 4.5 as the testing framework.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><ulink url="http://testng.org/">TestNG</ulink>: <para><ulink url="http://testng.org/">TestNG</ulink>: a testing
a testing framework inspired by JUnit 3.8 with added support framework inspired by JUnit 3.8 with added support for Java 5
for Java 5 annotations, test groups, data-driven testing, distributed annotations, test groups, data-driven testing, distributed testing,
testing, etc.</para> etc.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><ulink url="http://www.mockobjects.com/">MockObjects.com</ulink>: <para><ulink
a website dedicated to mock objects, a technique for improving the design url="http://www.mockobjects.com/">MockObjects.com</ulink>: a website
of code within Test-Driven Development.</para> dedicated to mock objects, a technique for improving the design of
code within Test-Driven Development.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><ulink url="http://en.wikipedia.org/wiki/Mock_Object">"Mock Objects"</ulink>: <para><ulink url="http://en.wikipedia.org/wiki/Mock_Object">"Mock
article at Wikipedia.</para> Objects"</ulink>: article at Wikipedia.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><ulink url="http://www.easymock.org/">EasyMock</ulink>: <para><ulink url="http://www.easymock.org/">EasyMock</ulink>: the
the Spring Framework uses EasyMock extensively in its test suite.</para> Spring Framework uses EasyMock extensively in its test suite.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><ulink url="http://www.jmock.org/">JMock</ulink>: <para><ulink url="http://www.jmock.org/">JMock</ulink>: a library that
a library that supports test-driven development of Java code supports test-driven development of Java code with mock
with mock objects.</para> objects.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><ulink url="http://dbunit.sourceforge.net/">DbUnit</ulink>: <para><ulink url="http://dbunit.sourceforge.net/">DbUnit</ulink>: a
a JUnit extension (also usable with Ant and Maven) targeted for database-driven JUnit extension (also usable with Ant and Maven) targeted for
projects that, among other things, puts your database into a known state database-driven projects that, among other things, puts your database
between test runs.</para> into a known state between test runs.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><ulink url="http://grinder.sourceforge.net/">Grinder</ulink>: <para><ulink url="http://grinder.sourceforge.net/">Grinder</ulink>: a
a Java load testing framework.</para> Java load testing framework.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</section> </section>
</chapter> </chapter>

File diff suppressed because it is too large Load Diff