[SPR-7849] work in progress: revising the testing chapter based on internal review.

This commit is contained in:
Sam Brannen 2010-12-30 05:47:23 +00:00
parent 54a7ad9f74
commit b8ab33e0c5
1 changed files with 167 additions and 159 deletions

View File

@ -100,11 +100,12 @@
<listitem> <listitem>
<para>Spring's support for annotations such as <para>Spring's support for annotations such as
<interfacename>@Autowired</interfacename> and <interfacename>@Autowired</interfacename>,
<interfacename>@Inject</interfacename>, and
<interfacename>@Resource,</interfacename> which provides <interfacename>@Resource,</interfacename> which provides
dependency injection for <literal>private</literal> or dependency injection for <literal>private</literal> or
<literal>protected</literal> fields, setter methods, and <literal>protected</literal> fields, setter methods, and
configuration methods</para> configuration methods.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</section> </section>
@ -155,7 +156,7 @@
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>The Spring Framework provides first class support for <para>The Spring Framework provides first-class support for
integration testing in integration testing in
the <filename class="libraryfile">spring-test</filename> module. the <filename class="libraryfile">spring-test</filename> module.
The name of the actual jar file might include the release The name of the actual jar file might include the release
@ -196,30 +197,28 @@
<title>Goals of integration testing</title> <title>Goals of integration testing</title>
<para>Spring's integration testing support has the following <para>Spring's integration testing support has the following
goals:</para> primary goals:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para><link linkend="testing-ctx-management">Spring IoC container <para>To manage <link linkend="testing-ctx-management">Spring IoC container
caching</link> between test execution.</para> caching</link> between test execution.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><link linkend="testing-fixture-di">Dependency Injection of <para>To provide <link linkend="testing-fixture-di">Dependency Injection of
test fixture instances</link>.</para> test fixture instances</link>.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><link linkend="testing-tx">Transaction management</link> <para>To provide <link linkend="testing-tx">transaction management</link>
appropriate to integration testing.</para> appropriate to integration testing.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><link linkend="testing-support-classes">Spring-specific <para>To supply <link linkend="testing-support-classes">Spring-specific
support classes</link> that are useful in writing integration base classes</link> that assist developers in writing integration
tests.<!--How is the last bullet point a *goal*? A goal is what the testing support is supposed to accomplish. Does customer write integration tests.</para>
tests? Aren't these already provided?--></para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -232,7 +231,7 @@ tests? Aren't these already provided?--></para>
<para>The Spring TestContext Framework provides consistent loading of <para>The Spring TestContext Framework provides consistent loading of
Spring <classname>ApplicationContext</classname>s and caching of those Spring <classname>ApplicationContext</classname>s and caching of those
contexts. Support for the caching of loaded contexts is important, contexts. Support for the caching of loaded contexts is important,
because startup time can become an issue - not because of the overhead because startup time can become an issue &mdash; not because of the overhead
of Spring itself, but because the objects instantiated by the Spring of Spring itself, but because the objects instantiated by the Spring
container take time to instantiate. For example, a project with 50 to 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 100 Hibernate mapping files might take 10 to 20 seconds to load the
@ -241,7 +240,7 @@ tests? Aren't these already provided?--></para>
productivity.</para> productivity.</para>
<para>Test classes provide an array containing the resource locations <para>Test classes provide an array containing the resource locations
of XML configuration metadata - typically in the classpath - that is of XML configuration metadata &mdash; typically in the classpath &mdash; that is
used to configure the application. These locations are the same as or used to configure the application. These locations are the same as or
similar to the list of configuration locations specified in similar to the list of configuration locations specified in
<literal>web.xml</literal> or other deployment configuration <literal>web.xml</literal> or other deployment configuration
@ -251,9 +250,9 @@ tests? Aren't these already provided?--></para>
<interfacename>ApplicationContext</interfacename> is reused for each <interfacename>ApplicationContext</interfacename> is reused for each
test. Thus the setup cost is incurred only once (per test fixture), test. Thus the setup cost is incurred only once (per test fixture),
and subsequent test execution is much faster. In the unlikely case and subsequent test execution is much faster. In the unlikely case
that a test corrupts the application context and requires reloading -- that a test corrupts the application context and requires reloading &mdash;
for example, by changing a bean definition or the state of an for example, by modifying a bean definition or the state of an
application object-- a Spring testing support mechanism causes the application object &mdash; a Spring testing support mechanism causes the
test fixture to reload the configurations and rebuilds the application test fixture to reload the configurations and rebuilds the application
context before executing the next test.</para> context before executing the next test.</para>
@ -273,8 +272,7 @@ tests? Aren't these already provided?--></para>
contexts across various testing scenarios (e.g., for configuring contexts across various testing scenarios (e.g., for 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>
<para>As an example, consider the scenario where we have a class, <para>As an example, consider the scenario where we have a class,
<classname>HibernateTitleDao</classname>, that performs data access <classname>HibernateTitleDao</classname>, that performs data access
@ -292,7 +290,7 @@ tests? Aren't these already provided?--></para>
<listitem> <listitem>
<para>The Hibernate mapping file configuration: is everything <para>The Hibernate mapping file configuration: is everything
mapped correctly and are the correct lazy-loading settings in mapped correctly, and are the correct lazy-loading settings in
place?</para> place?</para>
</listitem> </listitem>
@ -303,7 +301,7 @@ tests? Aren't these already provided?--></para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>See: dependency injection of test fixtures with the <link <para>See dependency injection of test fixtures with the <link
linkend="testcontext-fixture-di">TestContext Framework</link>.</para> linkend="testcontext-fixture-di">TestContext Framework</link>.</para>
</section> </section>
@ -313,8 +311,8 @@ tests? Aren't these already provided?--></para>
<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 data Also, many operations &mdash; such as inserting or modifying persistent data
- cannot be performed (or verified) outside a transaction.</para> &mdash; cannot be performed (or verified) outside a transaction.</para>
<para>The TestContext framework addresses this issue. By default, the <para>The TestContext framework addresses this issue. By default, the
framework will create and roll back a transaction for each test. You framework will create and roll back a transaction for each test. You
@ -328,9 +326,9 @@ tests? Aren't these already provided?--></para>
a <classname>PlatformTransactionManager</classname> bean defined in a <classname>PlatformTransactionManager</classname> bean defined in
the test's application context.</para> the test's application context.</para>
<para>If you want a transaction to commit - unusual, but occasionally <para>If you want a transaction to commit &mdash; 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 instructed to cause the database &mdash; the TestContext framework can be instructed to cause the
transaction to commit instead of roll back via the <link transaction to commit instead of roll back via the <link
linkend="integration-testing-annotations"><interfacename>@TransactionConfiguration</interfacename></link> linkend="integration-testing-annotations"><interfacename>@TransactionConfiguration</interfacename></link>
and <link and <link
@ -358,16 +356,15 @@ tests? Aren't these already provided?--></para>
</listitem> </listitem>
<listitem> <listitem>
<para>A <classname>SimpleJdbcTemplate</classname>, for querying to <para>A <classname>SimpleJdbcTemplate</classname>, for executing
confirm state. For example, you use an ORM tool to query before SQL statements to query the database.
and after testing application code that creates an object and Such queries can be used to confirm database state both
persists it<!--Revised to clarify: *you use an ORM tool to query* before and after testing app code? Or *what* is using the ORM tool to do what?-->, <emphasis>prior to</emphasis> and <emphasis>after</emphasis>
to verify that the data appears in the database. (Spring ensures execution of database-related application code, and Spring
that the query runs in the scope of the same transaction.) You ensures that such queries run in the scope of the same
need to tell your ORM tool to 'flush' its changes, by using, for transaction as the application code. When used in conjunction
example, the <methodname>flush()</methodname> method on with an ORM tool, be sure to avoid
Hibernate's <interfacename>Session</interfacename> <link linkend="testcontext-tx-false-positives">false positives</link>.</para>
interface.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -398,9 +395,7 @@ tests? Aren't these already provided?--></para>
</section> </section>
<section id="integration-testing-annotations"> <section id="integration-testing-annotations">
<title>Annotations<!--See highlighted area directly below with double-lined bar: what does this mean? Is something missing?--></title> <title>Annotations</title>
<!-- =============================================================== -->
<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 can use in <emphasis>Spring-specific</emphasis> annotations that you can use in
@ -421,7 +416,7 @@ tests? Aren't these already provided?--></para>
well as the <interfacename>ContextLoader</interfacename> strategy to well as the <interfacename>ContextLoader</interfacename> strategy to
use for loading the context.</para> use for loading the context.</para>
<programlisting language="java">@ContextConfiguration(locations={"example/test-context.xml"}, loader=CustomContextLoader.class) <programlisting language="java">@ContextConfiguration(locations="example/test-context.xml", loader=CustomContextLoader.class)
public class CustomConfiguredApplicationContextTests { public class CustomConfiguredApplicationContextTests {
<lineannotation>// class body...</lineannotation> <lineannotation>// class body...</lineannotation>
}</programlisting> }</programlisting>
@ -441,9 +436,11 @@ public class CustomConfiguredApplicationContextTests {
<para>Indicates that the underlying Spring <para>Indicates that the underlying Spring
<interfacename>ApplicationContext</interfacename> has been <interfacename>ApplicationContext</interfacename> has been
<emphasis>dirtied</emphasis> (modified)<!--meaning modified (see line after bullet list)? If not, indicate in parentheses what dirtied means. If you mean corrupted, say that.-->as <emphasis>dirtied</emphasis> (i.e., modified or corrupted in some manner)
follows during the execution of a test and should be closed, during the execution of a test and should be closed,
regardless of whether the test passed:</para> regardless of whether the test passed.
<interfacename>@DirtiesContext</interfacename> is supported in
the following scenarios:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -467,23 +464,26 @@ public class CustomConfiguredApplicationContextTests {
example, by replacing a bean definition). Subsequent tests are example, by replacing a bean definition). Subsequent tests are
supplied a new context.</para> supplied a new context.</para>
<para><note> <warning>
<title>Limitations of <title>Limitations of
<interfacename>@DirtiesContext</interfacename> with JUnit <interfacename>@DirtiesContext</interfacename> at the class level</title>
3.8<!--JUnit 3.8 and earlier? Later? ONLY JUnit 3.8? Specify.--></title>
<para>In a JUnit 3.8 environment <para>JUnit 4+ and TestNG both support class-level lifecycle
callbacks &mdash; for example, via <interfacename>@BeforeClass</interfacename>
and <interfacename>@AfterClass</interfacename> annotations. Consequently,
<interfacename>@DirtiesContext</interfacename> can be used at the class level
with these frameworks. JUnit 3.x, however, does not support
<emphasis>before class</emphasis> or <emphasis>after class</emphasis>
lifecycle callbacks. Thus, in a JUnit 3.x environment
<interfacename>@DirtiesContext</interfacename> is only supported <interfacename>@DirtiesContext</interfacename> is only supported
on methods and thus not at the class level.<!--IMPORTANT: This note contradicts next paragraph re *you can use @DirtiesContext as class level annotation.* I have on methods and not at the class level.</para>
</warning>
moved the note up, because you need to know this before you start reading about class level. --></para> <para>If class-level usage of <interfacename>@DirtiesContext</interfacename>
</note></para> is supported (e.g., with JUnit 4.5+ or TestNG), you can use
<interfacename>@DirtiesContext</interfacename> as both a class-level
<para>You can use <interfacename>@DirtiesContext</interfacename> as and method-level annotation within the same test class. In such scenarios,
a class-level and method-level annotation within the same class. the <interfacename>ApplicationContext</interfacename> is marked as
<!--Revise to clarify here what the exception is to preceding statement; note says with JUnit 3.8 this context not supported at class level.-->In
such scenarios, the
<interfacename>ApplicationContext</interfacename> is marked as
<emphasis>dirty</emphasis> after any such annotated method as well <emphasis>dirty</emphasis> after any such annotated method as well
as after the entire class. If the <classname>ClassMode</classname> as after the entire class. If the <classname>ClassMode</classname>
is set to <literal>AFTER_EACH_TEST_METHOD</literal>, the context is is set to <literal>AFTER_EACH_TEST_METHOD</literal>, the context is
@ -518,7 +518,7 @@ public void testProcessWhichDirtiesAppCtx() {
<para>Defines class-level metadata for configuring which <para>Defines class-level metadata for configuring which
<interfacename>TestExecutionListener</interfacename>s should be <interfacename>TestExecutionListener</interfacename>s should be
registered with a <classname>TestContextManager</classname>. registered with the <classname>TestContextManager</classname>.
Typically, <interfacename>@TestExecutionListeners</interfacename> Typically, <interfacename>@TestExecutionListeners</interfacename>
are used in conjunction with are used in conjunction with
<interfacename>@ContextConfiguration</interfacename>.</para> <interfacename>@ContextConfiguration</interfacename>.</para>
@ -542,8 +542,8 @@ public class CustomTestExecutionListenerTests {
tests. Specifically, the bean name of the tests. Specifically, the bean name of the
<interfacename>PlatformTransactionManager</interfacename> that is to <interfacename>PlatformTransactionManager</interfacename> that is to
be used to drive transactions can be explicitly configured if the be used to drive transactions can be explicitly configured if the
bean name of the desired PlatformTransactionManager is not bean name of the desired <interfacename>PlatformTransactionManager</interfacename>
"transactionManager". In addition, you can change the is not "transactionManager". In addition, you can change the
<literal>defaultRollback</literal> flag to <literal>false</literal>. <literal>defaultRollback</literal> flag to <literal>false</literal>.
Typically, <interfacename>@TransactionConfiguration</interfacename> Typically, <interfacename>@TransactionConfiguration</interfacename>
is used in conjunction with is used in conjunction with
@ -554,6 +554,17 @@ public class CustomTestExecutionListenerTests {
public class CustomConfiguredTransactionalTests { public class CustomConfiguredTransactionalTests {
<lineannotation>// class body...</lineannotation> <lineannotation>// class body...</lineannotation>
}</programlisting> }</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>
<listitem> <listitem>
@ -635,15 +646,13 @@ public void testProcessWithoutTransaction() {
<interfacename>@Transactional</interfacename>; doing so allows a <interfacename>@Transactional</interfacename>; doing so allows a
mix of transactional and non-transactional methods in the same mix of transactional and non-transactional methods in the same
test class without the need for using test class without the need for using
<interfacename>@NotTransactional</interfacename>.<!--Is text missing below? (where double bar is. Delete bar?)--></para> <interfacename>@NotTransactional</interfacename>.</para>
</warning> </warning>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<!-- =============================================================== -->
<para>The following annotations are <emphasis>only</emphasis> supported <para>The following annotations are <emphasis>only</emphasis> supported
when used in conjunction with JUnit (that is., with the <link when used in conjunction with JUnit (that is, 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.2</link> and <link 3.8.2</link> and <link
@ -771,7 +780,7 @@ public void testProcessWithOneSecondTimeout() {
<para>The scope of execution to be repeated includes execution of <para>The scope of execution to be repeated includes execution of
the test method itself as well as any <emphasis>set up</emphasis> or the test method itself as well as any <emphasis>set up</emphasis> or
<emphasis>tear down</emphasis> of the test fixture.<!--GLOBAL: What is up with highlighted double bars throughout this file?--></para> <emphasis>tear down</emphasis> of the test fixture.</para>
<programlisting language="java">@Repeat(10) <programlisting language="java">@Repeat(10)
@Test @Test
@ -781,8 +790,6 @@ public void testProcessRepeatedly() {
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<!-- =============================================================== -->
<para>The following non-test-specific annotations are supported with <para>The following non-test-specific annotations are supported with
standard semantics for all configurations of the Spring TestContext standard semantics for all configurations of the Spring TestContext
Framework.</para> Framework.</para>
@ -878,8 +885,6 @@ public void testProcessRepeatedly() {
linkend="integration-testing-annotations">annotation support</link> linkend="integration-testing-annotations">annotation support</link>
sections.</para> sections.</para>
<!-- ================================================================= -->
<section id="testcontext-key-abstractions"> <section id="testcontext-key-abstractions">
<title>Key abstractions</title> <title>Key abstractions</title>
@ -912,10 +917,29 @@ public void testProcessRepeatedly() {
which manages a single <classname>TestContext</classname> and which manages a single <classname>TestContext</classname> and
signals events to all registered signals events to all registered
<interfacename>TestExecutionListener</interfacename>s at <interfacename>TestExecutionListener</interfacename>s at
well-defined test execution points: test instance preparation, well-defined test execution points:</para>
prior to any <emphasis>before methods</emphasis> of a particular
testing framework, and after any <emphasis>after <itemizedlist>
methods</emphasis> of a particular testing framework.</para> <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>
<listitem> <listitem>
@ -928,14 +952,13 @@ public void testProcessRepeatedly() {
<para>Spring provides three <para>Spring provides three
<interfacename>TestExecutionListener</interfacename> <interfacename>TestExecutionListener</interfacename>
implementations that are configured by default: implementations that are configured by default:
<classname>DependencyInjectionTestExecutionListener</classname><classname>, <classname>DependencyInjectionTestExecutionListener</classname>,
DirtiesContextTestExecutionListener</classname>, and <classname>DirtiesContextTestExecutionListener</classname>, and
<classname>TransactionalTestExecutionListener</classname>. <classname>TransactionalTestExecutionListener</classname>.
Respectively, they support dependency injection of the test Respectively, they support dependency injection of the test
instance, handling of the instance, handling of the
<interfacename>@DirtiesContext</interfacename> annotation, and <interfacename>@DirtiesContext</interfacename> annotation, and
transactional test execution with default rollback transactional test execution with default rollback semantics.</para>
semantics.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -945,8 +968,6 @@ public void testProcessRepeatedly() {
with the framework.</para> with the framework.</para>
</section> </section>
<!-- ================================================================= -->
<section id="testcontext-ctx-management"> <section id="testcontext-ctx-management">
<title>Context management and caching</title> <title>Context management and caching</title>
@ -1018,8 +1039,8 @@ public class MyTest {
<interfacename>@ContextConfiguration</interfacename> with an array <interfacename>@ContextConfiguration</interfacename> with an array
that contains the resource locations of XML configuration metadata that contains the resource locations of XML configuration metadata
(assuming an XML-capable <interfacename>ContextLoader</interfacename> (assuming an XML-capable <interfacename>ContextLoader</interfacename>
has been configured) - typically in the classpath<!--*what* is in the classpath? This sentence is confusing. Please revise.--> has been configured) &mdash; typically in the classpath<!--*what* is in the classpath? This sentence is confusing. Please revise.-->
- used to configure the application. (See the following code example.) &mdash; used to configure the application. (See the following code example.)
This location will be the same, or nearly the same, as the list of This location will be the same, or nearly the same, as the list of
configuration locations specified in <literal>web.xml</literal> or configuration locations specified in <literal>web.xml</literal> or
other deployment configuration. Alternatively, you can implement and other deployment configuration. Alternatively, you can implement and
@ -1082,8 +1103,8 @@ public class ExtendedTest extends BaseTest {
test. Thus the setup cost is incurred only once (per test fixture), test. Thus the setup cost is incurred only once (per test fixture),
and subsequent test execution is much faster. In the unlikely case and subsequent test execution is much faster. In the unlikely case
that a test dirties (modifies)<!--dirty means modify? If not, revise to say what it does mean. If corrupted, say that.--> that a test dirties (modifies)<!--dirty means modify? If not, revise to say what it does mean. If corrupted, say that.-->
the application context, requiring reloading -- for example, by the application context, requiring reloading &mdash; for example, by
changing a bean definition or the state of an application object -- changing a bean definition or the state of an application object &mdash;
you can annotate your test method with you can annotate your test method with
<interfacename>@DirtiesContext</interfacename> (assuming <interfacename>@DirtiesContext</interfacename> (assuming
<classname>DirtiesContextTestExecutionListener</classname> has been <classname>DirtiesContextTestExecutionListener</classname> has been
@ -1092,15 +1113,13 @@ public class ExtendedTest extends BaseTest {
executing the next test. </para> executing the next test. </para>
</section> </section>
<!-- ================================================================= -->
<section id="testcontext-fixture-di"> <section id="testcontext-fixture-di">
<title>Dependency Injection of test fixtures</title> <title>Dependency Injection of test fixtures</title>
<para>When you configure the <para>When you configure the
<classname>DependencyInjectionTestExecutionListener</classname> -- <classname>DependencyInjectionTestExecutionListener</classname> &mdash;
which is configured by default through the which is configured by default through the
<interfacename>@TestExecutionListeners</interfacename> annotation-- <interfacename>@TestExecutionListeners</interfacename> annotation &mdash;
the dependencies of your test instances are the dependencies of your test instances are
<emphasis>injected</emphasis> from beans in the application context <emphasis>injected</emphasis> from beans in the application context
you configured through you configured through
@ -1154,7 +1173,8 @@ public class ExtendedTest extends BaseTest {
linkend="testing-fixture-di">Goals</link> section. (We will look at linkend="testing-fixture-di">Goals</link> section. (We will look at
the application context configuration after all sample code listings.) the application context configuration after all sample code listings.)
A JUnit 4-based implementation of the test class itself uses A JUnit 4-based implementation of the test class itself uses
<interfacename>@Autowired</interfacename> for field injection. <!--Refer to following code listing; indicate what it shows.--></para> <interfacename>@Autowired</interfacename> for field injection.
<!--Refer to following code listing; indicate what it shows.--></para>
<note> <note>
<para>The dependency injection behavior in the following code <para>The dependency injection behavior in the following code
@ -1186,8 +1206,6 @@ public final class HibernateTitleDaoTests {
} }
}</programlisting> }</programlisting>
<!-- =============================================================== -->
<para>Alternatively, you can configure the class to use <para>Alternatively, you can configure the class to use
<interfacename>@Autowired</interfacename> for setter injection.</para> <interfacename>@Autowired</interfacename> for setter injection.</para>
@ -1211,8 +1229,6 @@ public final class HibernateTitleDaoTests {
} }
}</programlisting> }</programlisting>
<!-- =============================================================== -->
<para>Here is an example of <interfacename>@Resource</interfacename> <para>Here is an example of <interfacename>@Resource</interfacename>
for field injection.</para> for field injection.</para>
@ -1232,8 +1248,6 @@ public final class HibernateTitleDaoTests {
} }
}</programlisting> }</programlisting>
<!-- =============================================================== -->
<para>Here is an example of <interfacename>@Resource</interfacename> <para>Here is an example of <interfacename>@Resource</interfacename>
for setter injection.</para> for setter injection.</para>
@ -1257,8 +1271,6 @@ public final class HibernateTitleDaoTests {
} }
}</programlisting> }</programlisting>
<!-- =============================================================== -->
<para>The preceding code listings use the same XML context file <para>The preceding code listings use the same XML context file
referenced by the <interfacename>@ContextConfiguration</interfacename> referenced by the <interfacename>@ContextConfiguration</interfacename>
annotation (that is, <literal>daos.xml</literal>), which looks like annotation (that is, <literal>daos.xml</literal>), which looks like
@ -1313,12 +1325,14 @@ public final class HibernateTitleDaoTests {
assuming that "myDataSource" is the bean id). If there is only one assuming that "myDataSource" is the bean id). If there is only one
<interfacename>DataSource</interfacename> bean to begin with, then <interfacename>DataSource</interfacename> bean to begin with, then
the qualifier does not have any effect, independent from the bean the qualifier does not have any effect, independent from the bean
name of that single matching bean.<!--What about the bean name of the single matching bean? Relate to rest of the sentence.--></para> name of that single matching bean.
<!--What about the bean name of the single matching bean? Relate to rest of the sentence.--></para>
<para>Alternatively, consider using the <para>Alternatively, consider using the
<interfacename>@Resource</interfacename> annotation on such <interfacename>@Resource</interfacename> annotation on such
overridden setter methods, defining the target bean name explicitly, overridden setter methods, defining the target bean name explicitly,
with no type matching semantics. Note that this <!--Revise preceding: indicate *what* always points to a bean with that specific name.-->always with no type matching semantics. Note that this
<!--Revise preceding: indicate *what* always points to a bean with that specific name.-->always
points to a bean with that specific name, no matter whether there is points to a bean with that specific name, no matter whether there is
one or more beans of the given type.</para> one or more beans of the given type.</para>
@ -1334,8 +1348,6 @@ public final class HibernateTitleDaoTests {
</note> </note>
</section> </section>
<!-- ================================================================= -->
<section id="testcontext-tx"> <section id="testcontext-tx">
<title>Transaction management</title> <title>Transaction management</title>
@ -1409,7 +1421,8 @@ public final class HibernateTitleDaoTests {
integration testing scenario highlighting several transaction-related integration testing scenario highlighting several transaction-related
annotations. Consult the <link annotations. Consult the <link
linkend="integration-testing-annotations">annotation support</link> linkend="integration-testing-annotations">annotation support</link>
section of the reference manual <!--If by reference manual you mean this manual, delete *of the reference manual*. If you mean another book, give name of it.-->for section of the reference manual
<!--If by reference manual you mean this manual, delete *of the reference manual*. If you mean another book, give name of it.-->for
further information and configuration examples.</para> further information and configuration examples.</para>
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class) <programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
@ -1447,13 +1460,17 @@ public class FictitiousTransactionalTest {
}</programlisting> }</programlisting>
<anchor id="testcontext-tx-false-positives"/>
<note> <note>
<title>Avoid false positives when testing ORM code</title> <title>Avoid false positives when testing ORM code</title>
<para>When you test code involving an ORM framework such as JPA or <para>When you test code involving an ORM framework such as JPA or
Hibernate, <emphasis>flush</emphasis> the underlying session within Hibernate, <emphasis>flush</emphasis> the underlying session within
test methods<!--Revise remainder of sentence: *,which updates (note comma and s) the state of the session* OR *that (not *which*) update the state of test methods
the session.* Two different meanings.--> which update the state of the <!--Revise remainder of sentence:
*,which updates (note comma and s) the state of the session*
OR *that (not *which*) update the state of the session.*
Two different meanings.--> which update the state of the
session. Failing to flush the ORM framework's underlying session can session. Failing to flush the ORM framework's underlying session can
produce <emphasis>false positives</emphasis>: your test may pass, produce <emphasis>false positives</emphasis>: your test may pass,
but the same code throws an exception in a live, production but the same code throws an exception in a live, production
@ -1484,8 +1501,6 @@ public void updateWithSessionFlush() {
</note> </note>
</section> </section>
<!-- ================================================================= -->
<section id="testcontext-support-classes"> <section id="testcontext-support-classes">
<title>TestContext support classes</title> <title>TestContext support classes</title>
@ -1505,11 +1520,12 @@ public void updateWithSessionFlush() {
JUnit 3.8 environment. When you extend the JUnit 3.8 environment. When you extend the
<classname>AbstractJUnit38SpringContextTests</classname> class, <classname>AbstractJUnit38SpringContextTests</classname> class,
you need access to the following <literal>protected</literal> you need access to the following <literal>protected</literal>
instance variables:<!--Either provide more variables or change *variables* above to *variable*. Also revise to indicate: you need access to this variable *in order* instance variables:
<!--Either provide more variables or change *variables* above to *variable*.
to extend aforementioned class? Not sure what preceding is saying.Next bullet point says when you extend the class, you *have* access Also revise to indicate: you need access to this variable *in order* to extend
aforementioned class? Not sure what preceding is saying.
to variables. i.e. extending class is what gives you access.--></para> Next bullet point says when you extend the class, you *have* access
to variables. i.e. extending class is what gives you access.--></para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -1543,18 +1559,15 @@ to variables. i.e. extending class is what gives you access.--></para>
</listitem> </listitem>
<listitem> <listitem>
<para><literal>simpleJdbcTemplate</literal>: Useful for <para><literal>simpleJdbcTemplate</literal>: Use this variable
querying to confirm state. For example, use an ORM tool to to execute SQL statements to query the database.
query before and after testing application code that creates Such queries can be used to confirm database state both
an object and persists it, <!--Revise sentence to indicate who or what uses ORM tool to do what. You use an ORM tool to query before and after testing app <emphasis>prior to</emphasis> and <emphasis>after</emphasis>
execution of database-related application code, and Spring
code, etc? Or what? If my rewording is wrong, revise to clarify. What does using an ORM tool have to do with simpleJdbcTemplate?-->to ensures that such queries run in the scope of the same
verify that the data appears in the database. (Spring transaction as the application code. When used in conjunction
ensures that the query runs in the scope of the same with an ORM tool, be sure to avoid
transaction.) You need to tell your ORM tool to 'flush' its <link linkend="testcontext-tx-false-positives">false positives</link>.</para>
changes for this to work correctly by, for example, using
the <methodname>flush()</methodname> method on Hibernate's
<classname>Session</classname> interface.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</listitem> </listitem>
@ -1607,21 +1620,21 @@ code, etc? Or what? If my rewording is wrong, revise to clarify. What does using
<listitem> <listitem>
<para><literal>applicationContext</literal>: Inherited from <para><literal>applicationContext</literal>: Inherited from
the <classname>AbstractJUnit4SpringContextTests</classname> the <classname>AbstractJUnit4SpringContextTests</classname>
superclass. Perform explicit bean lookups or test the state superclass. Use this variable to perform explicit bean
of the context as a whole.</para> lookups or to test the state of the context as a
whole.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><literal>simpleJdbcTemplate</literal>: Useful for <para><literal>simpleJdbcTemplate</literal>: Use this variable
querying to confirm state. For example, use an ORM tool to to execute SQL statements to query the database.
query before and after testing application code that creates Such queries can be used to confirm database state both
an object and persists it, to verify that the data appears <emphasis>prior to</emphasis> and <emphasis>after</emphasis>
in the database. <!--Same query applies here as with same text in previous section.-->(Spring execution of database-related application code, and Spring
ensures that the query runs in the scope of the same ensures that such queries run in the scope of the same
transaction.) You need to tell your ORM tool to 'flush' its transaction as the application code. When used in conjunction
changes for this to work correctly by, for example, using with an ORM tool, be sure to avoid
the <methodname>flush()</methodname> method on Hibernate's <link linkend="testcontext-tx-false-positives">false positives</link>.</para>
<classname>Session</classname> interface.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</listitem> </listitem>
@ -1630,8 +1643,8 @@ code, etc? Or what? If my rewording is wrong, revise to clarify. What does using
<tip> <tip>
<para>These classes are a convenience for extension. If you do not <para>These classes are a convenience for extension. If you do not
want your test classes to be tied to a Spring-specific class want your test classes to be tied to a Spring-specific class
hierarchy -- for example, if you want to extend directly the class hierarchy &mdash; for example, if you want to extend directly the class
you are testing -- you can configure your own custom test classes you are testing &mdash; you can configure your own custom test classes
by using by using
<interfacename>@RunWith(SpringJUnit4ClassRunner.class)</interfacename>, <interfacename>@RunWith(SpringJUnit4ClassRunner.class)</interfacename>,
<interfacename>@ContextConfiguration</interfacename>, <interfacename>@ContextConfiguration</interfacename>,
@ -1714,21 +1727,21 @@ public class SimpleTest {
<listitem> <listitem>
<para><literal>applicationContext</literal>: Inherited from <para><literal>applicationContext</literal>: Inherited from
the <classname>AbstractTestNGSpringContextTests</classname> the <classname>AbstractTestNGSpringContextTests</classname>
superclass. Perform explicit bean lookups or test the state superclass. Use this variable to perform explicit bean
of the context as a whole.</para> lookups or to test the state of the context as a
whole.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><literal>simpleJdbcTemplate</literal>: Useful for <para><literal>simpleJdbcTemplate</literal>: Use this variable
querying to confirm state. For example, use an ORM tool <!--Same change and query as above-->to to execute SQL statements to query the database.
query before and after testing application code that creates Such queries can be used to confirm database state both
an object and persists it, to verify that the data appears <emphasis>prior to</emphasis> and <emphasis>after</emphasis>
in the database. (Spring ensures that the query runs in the execution of database-related application code, and Spring
scope of the same transaction.) You need to tell your ORM ensures that such queries run in the scope of the same
tool to 'flush' its changes for this to work correctly by, transaction as the application code. When used in conjunction
for example, using the <methodname>flush()</methodname> with an ORM tool, be sure to avoid
method on Hibernate's <classname>Session</classname> <link linkend="testcontext-tx-false-positives">false positives</link>.</para>
interface.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</listitem> </listitem>
@ -1737,8 +1750,8 @@ public class SimpleTest {
<tip> <tip>
<para>These classes are a convenience for extension. If you do not <para>These classes are a convenience for extension. If you do not
want your test classes to be tied to a Spring-specific class want your test classes to be tied to a Spring-specific class
hierarchy--for example, if you want to directly extend the class hierarchy &mdash; for example, if you want to directly extend the class
you are testing--you can configure your own custom test classes by you are testing &mdash; you can configure your own custom test classes by
using <interfacename>@ContextConfiguration</interfacename>, using <interfacename>@ContextConfiguration</interfacename>,
<interfacename>@TestExecutionListeners</interfacename>, and so on, <interfacename>@TestExecutionListeners</interfacename>, and so on,
and by manually instrumenting your test class with a and by manually instrumenting your test class with a
@ -1748,12 +1761,8 @@ public class SimpleTest {
</tip> </tip>
</section> </section>
</section> </section>
<!-- ================================================================= -->
</section> </section>
<!-- === PetClinic Example ================================================= -->
<section id="testing-examples-petclinic"> <section id="testing-examples-petclinic">
<title>PetClinic example</title> <title>PetClinic example</title>
@ -1802,8 +1811,8 @@ public abstract class AbstractClinicTests <emphasis role="bold">extends Abstract
</listitem> </listitem>
<listitem> <listitem>
<para>The <literal>clinic</literal> instance variable - the <para>The <literal>clinic</literal> instance variable &mdash; the
application object being tested - is set by Dependency Injection application object being tested &mdash; is set by Dependency Injection
through <interfacename>@Autowired</interfacename> semantics.</para> through <interfacename>@Autowired</interfacename> semantics.</para>
</listitem> </listitem>
@ -1821,8 +1830,9 @@ public abstract class AbstractClinicTests <emphasis role="bold">extends Abstract
<para>Like many integration tests that use a database, most of the <para>Like many integration tests that use a database, most of the
tests in <classname>AbstractClinicTests</classname> depend on a tests in <classname>AbstractClinicTests</classname> depend on a
minimum amount of data already in the database before the test cases minimum amount of data already in the database before the test cases
run. You might, however, choose to populate the database in <!--do you mean populate the database *with* your test cases?-->your run. You might, however, choose to populate the database in
test cases also - again, within the same transaction.</para> <!--do you mean populate the database *with* your test cases?-->your
test cases also &mdash; again, within the same transaction.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -1863,7 +1873,7 @@ public class HibernateClinicTests extends AbstractClinicTests { }
is typical of large-scale applications, configuration locations are is typical of large-scale applications, configuration locations are
often specified in a common base class for all application-specific often specified in a common base class for all application-specific
integration tests. Such a base class may also add useful instance integration tests. Such a base class may also add useful instance
variables--populated by Dependency Injection, naturally--such as a variables &mdash; populated by Dependency Injection, naturally &mdash; such as a
<classname>HibernateTemplate</classname>, in the case of an application <classname>HibernateTemplate</classname>, in the case of an application
using Hibernate.</para> using Hibernate.</para>
@ -1888,8 +1898,6 @@ public class HibernateClinicTests extends AbstractClinicTests { }
files for connection settings: see the PetClinic application for an files for connection settings: see the PetClinic application for an
example.</para> example.</para>
</section> </section>
<!-- ======================================================================= -->
</section> </section>
<section id="testing-resources"> <section id="testing-resources">