diff --git a/spring-framework-reference/src/testing.xml b/spring-framework-reference/src/testing.xml index d743320439..c5b58d545e 100644 --- a/spring-framework-reference/src/testing.xml +++ b/spring-framework-reference/src/testing.xml @@ -5,44 +5,39 @@ Testing
- Introduction + Introduction to testing - The Spring team considers developer testing to be an absolutely - integral part of enterprise software development. A thorough treatment of - testing in the enterprise is beyond the scope of this chapter; rather, the - focus here is on the value-add that the adoption of the IoC principle can - bring to unit testing and on the - benefits that the Spring Framework provides in integration testing. + Testing is an integral part of enterprise software development. This + chapter focuses on the value-add of the IoC principle to unit testing and on the benefits of Spring + Framework integration testing. + (A thorough treatment of testing in the enterprise is beyond the scope of + this chapter.)
Unit testing - One of the main benefits of Dependency Injection is that your code - should really depend far less on the container than in traditional Java EE - development. The POJOs that make up your application should be testable in - JUnit or TestNG tests, with objects simply instantiated using the - new operator, without Spring or any other - container. You can use mock - objects (in conjunction with many other valuable testing - techniques) to test your code in isolation. If you follow the architecture - recommendations around Spring you will find that the resulting clean - layering and componentization of your codebase will naturally facilitate - easier unit testing. For example, you will be able to - test service layer objects by stubbing or mocking DAO or Repository - interfaces, without any need to access persistent data while running unit - tests. + Dependency Injection should make your code less dependent on the + container than it would be with traditional Java EE development. The POJOs + that make up your application should be testable in JUnit or TestNG tests, + with objects simply instantiated using the new + operator, without Spring or any other container. You + can use mock objects (in conjunction + with other valuable testing techniques) to test your code in isolation. If + you follow the architecture recommendations for Spring, the resulting + clean layering and componentization of your codebase will facilitate + easier unit testing. For example, you can test service layer objects by + stubbing or mocking DAO or Repository interfaces, without needing to + access persistent data while running unit tests. - True unit tests typically will run extremely quickly, as there is no - runtime infrastructure to set up, whether application server, database, - ORM tool, or whatever. Thus emphasizing true unit tests as part of your - development methodology will boost your productivity. The upshot of this - is that you often do not need this section of the testing chapter to help - you write effective unit tests for your IoC-based - applications. For certain unit testing scenarios, however, the Spring - Framework provides the following mock objects and testing support - classes. + True unit tests typically run extremely quickly, as there is no + runtime infrastructure to set up. Emphasizing true unit tests as part of + your development methodology will boost your productivity. You may not + need this section of the testing chapter to help you write effective unit + tests for your IoC-based applications. For certain unit testing scenarios, + however, the Spring Framework provides the following mock objects and + testing support classes.
Mock objects @@ -51,11 +46,11 @@ JNDI The org.springframework.mock.jndi package - contains an implementation of the JNDI SPI, which is useful for - setting up a simple JNDI environment for test suites or stand-alone + contains an implementation of the JNDI SPI, which you can use to set + up a simple JNDI environment for test suites or stand-alone applications. If, for example, JDBC DataSources get bound to the same JNDI names in test code as within a Java EE - container, both application code and configuration can be reused in + container, you can reuse both application code and configuration in testing scenarios without modification.
@@ -66,10 +61,10 @@ contains a comprehensive set of Servlet API mock objects, targeted at usage with Spring's Web MVC framework, which are useful for testing web contexts and controllers. These mock objects are generally more - convenient to use than dynamic mock objects (e.g., EasyMock) or existing Servlet - API mock objects (e.g., MockObjects). + convenient to use than dynamic mock objects such as EasyMock or existing Servlet API + mock objects such as MockObjects.
@@ -89,26 +84,25 @@ The org.springframework.test.util package contains ReflectionTestUtils, which is a - collection of reflection-based utility methods for use in unit and - integration testing scenarios in which the developer would benefit - from being able to set a non-public field or invoke - a non-public setter method when testing application + collection of reflection-based utility methods. Developers use these + methods in unit and integration testing scenarios in which they need + to set a non-public field or invoke a + non-public setter method when testing application code involving, for example: - ORM frameworks such as JPA and Hibernate which condone the - usage of private or - protected field access as opposed to - public setter methods for properties in a - domain entity + ORM frameworks such as JPA and Hibernate that condone + private or protected field + access as opposed to public setter methods for + properties in a domain entity. Spring's support for annotations such as @Autowired and - @Resource which provides dependency - injection for private or + @Resource, which provides + dependency injection for private or protected fields, setter methods, and configuration methods @@ -119,10 +113,9 @@ Spring MVC The org.springframework.test.web package - contains ModelAndViewAssert, which can be used - in combination with any testing framework (e.g., JUnit 4+, TestNG, - etc.) for unit tests dealing with Spring MVC - ModelAndView objects. + contains ModelAndViewAssert, which you can use + in combination with JUnit 4+, TestNG, and so on for unit tests dealing + with Spring MVC ModelAndView objects. Unit testing Spring MVC Controllers @@ -130,7 +123,7 @@ To test your Spring MVC Controllers, use ModelAndViewAssert combined with MockHttpServletRequest, - MockHttpSession, etc. from the MockHttpSession, and so on from the org.springframework.mock.web package. @@ -165,41 +158,39 @@ The Spring Framework provides first class support for integration testing in the org.springframework.test-VERSION.jar - library (where VERSION is the release version). In - this library, you will find the - org.springframework.test package which contains - valuable classes for integration testing using a Spring container, while - at the same time not being reliant on an application server or other - 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. + library (where VERSION is the release version). This + library includes the org.springframework.test + package, which contains valuable classes for integration testing with a + Spring container. This testing does not rely on an application server or + other deployment environment. Such tests are slower to run than unit + tests but much faster to than the equivalent Cactus tests or remote + tests that rely on deployment to an application server. - Since Spring 2.5, unit and integration testing support is provided - in the form of the annotation-driven In Spring 2.5 and later, unit and integration testing support is + provided in the form of the annotation-driven Spring TestContext Framework. The TestContext Framework is agnostic of the actual testing framework in use, thus allowing instrumentation of tests in various environments - including JUnit, TestNG, etc. + including JUnit, TestNG, and so on. Legacy JUnit 3.8 class hierarchy is deprecated - As of Spring 3.0, the legacy JUnit 3.8 base class hierarchy - (e.g., + As of Spring 3.0, the legacy JUnit 3.8 base class hierarchy (for + example, AbstractDependencyInjectionSpringContextTests, AbstractTransactionalDataSourceSpringContextTests, 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 - migrated to the Spring + Migrate this code to the Spring TestContext Framework.
- Goals + Goals of integration testing - The following bullet points highlight the fundamental goals of - Spring's integration testing support: + Spring's integration testing support has the following + goals: @@ -209,25 +200,25 @@ Dependency Injection of - test fixture instances (this is nice). + test fixture instances. Transaction management - appropriate to integration testing (this is even nicer). + appropriate to integration testing. Spring-specific - support classes that are really useful when writing - integration tests. + support classes that are useful in writing integration + tests. - In the next few sections each of the above goals is discussed in - greater detail, and at the end of each section you will find a direct - link to implementation and configuration details pertaining to that - particular goal. + The next few sections describe each goal and provide links to + implementation and configuration details.
Context management and caching @@ -235,32 +226,32 @@ The Spring TestContext Framework provides consistent loading of Spring ApplicationContexts and caching of those contexts. Support for the caching of loaded contexts is important, - because if you are working on a large project, startup time may become - an issue - not because of the overhead of Spring itself, but because - the objects instantiated by the Spring container will themselves take - time to instantiate. For example, a project with 50-100 Hibernate - mapping files might take 10-20 seconds to load the mapping files, and - incurring that cost before running every single test in every single - test fixture will lead to slower overall test runs that could reduce + because startup time can become an issue - not because of the overhead + of Spring itself, but because the objects instantiated by the Spring + container take time to instantiate. For example, a project with 50 to + 100 Hibernate mapping files might take 10 to 20 seconds to load the + mapping files, and incurring that cost before running every test in + every test fixture leads to slower overall test runs that could reduce productivity. Test classes provide an array containing the resource locations - of XML configuration metadata - typically on the classpath - used to - configure the application. This will be the same, or nearly the same, - as the list of configuration locations specified in - web.xml or other deployment configuration. + of XML configuration metadata - typically in the classpath - that is + used to configure the application. These locations are the same as or + similar to the list of configuration locations specified in + web.xml or other deployment configuration + files. By default, once loaded, the configured - ApplicationContext will be reused for - each test. Thus the setup cost will be incurred only once (per test - fixture), and subsequent test execution will be much faster. In the - unlikely case that a test may 'dirty' the application context, - requiring reloading - for example, by changing a bean definition or - the state of an application object - Spring's testing support provides - a mechanism to cause the test fixture to reload the configurations and - rebuild the application context before executing the next test. + ApplicationContext is reused for each + test. Thus the setup cost is incurred only once (per test fixture), + and subsequent test execution is much faster. In the unlikely case + that a test corrupts the application context and requires reloading -- + for example, by changing a bean definition or the state of an + application object-- a Spring testing support mechanism causes the + test fixture to reload the configurations and rebuilds the application + context before executing the next test. - See: context management and caching with the See context management and caching with the TestContext Framework.
@@ -271,7 +262,7 @@ When the TestContext framework loads your application context, it can optionally configure instances of your test classes via Dependency Injection. This provides a convenient mechanism for setting - up test fixtures using pre-configured beans from your application + up test fixtures using preconfigured beans from your application context. A strong benefit here is that you can reuse application contexts across various testing scenarios (e.g., for configuring Spring-managed object graphs, transactional proxies, @@ -340,45 +331,45 @@ linkend="integration-testing-annotations">@Rollback annotations. - See: transaction management with the See transaction management with the TestContext Framework.
- Integration testing support classes + Support classes for integration testing The Spring TestContext Framework provides several - abstract support classes that can simplify writing - integration tests. These base test classes provide well defined hooks - into the testing framework as well as convenient instance variables - and methods, allowing access to such things as: + abstract support classes that simplify the writing + of integration tests. These base test classes provide well-defined + hooks into the testing framework as well as convenient instance + variables and methods, which enable you to access: - The ApplicationContext: useful for - performing explicit bean lookups or testing the state of the - context as a whole. + The ApplicationContext, for performing + explicit bean lookups or testing the state of the context as a + whole. - A SimpleJdbcTemplate: useful for - querying to confirm state. For example, you might query before and - after testing application code that creates an object and persists - 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 - the same transaction.) You will need to tell your ORM tool to - 'flush' its changes for this to work correctly, for example using - the flush() method on Hibernate's - Session interface. + A SimpleJdbcTemplate, for querying to + confirm state. For example, you use an ORM tool to query before + and after testing application code that creates an object and + persists it, + to verify that the data appears in the database. (Spring ensures + that the query runs in the scope of the same transaction.) You + need to tell your ORM tool to 'flush' its changes, by using, for + example, the flush() method on + Hibernate's Session + interface. - In addition, you may find it desirable to provide your own - custom, application-wide superclass for integration tests that - provides further useful instance variables and methods specific to - your project. + In addition, you may want to create your own custom, + application-wide superclass with instance variables and methods + specific to your project. - See: support classes for the See support classes for the TestContext Framework.
@@ -401,7 +392,7 @@
- Annotations + Annotations<!--See highlighted area directly below with double-lined bar: what does this mean? Is something missing?--> @@ -409,32 +400,33 @@ Spring-specific annotations that you can use in your unit and integration tests in conjunction with the TestContext framework. Refer to the respective JavaDoc for further information, - including default attribute values, attribute aliases, etc. + including default attribute values, attribute aliases, and so on. @ContextConfiguration - Defines class-level metadata which is used to determine how to + Defines class-level metadata that is used to determine how to load and configure an ApplicationContext. Specifically, @ContextConfiguration defines the - application context resource locations to - load as well as the ContextLoader - strategy to use for loading the context. + application context resource locations to load as + well as the ContextLoader strategy to + use for loading the context. @ContextConfiguration(locations={"example/test-context.xml"}, loader=CustomContextLoader.class) public class CustomConfiguredApplicationContextTests { // class body... } - Note: @ContextConfiguration - provides support for inherited resource - locations by default. See the Context management and - caching section and JavaDoc for an example and further - details. + + @ContextConfiguration + supports inherited resource locations by + default. See Context + management and caching and JavaDoc for an example and + further details. + @@ -443,36 +435,52 @@ public class CustomConfiguredApplicationContextTests { Indicates that the underlying Spring ApplicationContext has been - dirtied during the execution of a test and - should be closed (regardless of whether the test passed or not): - + dirtied (modified)as + follows during the execution of a test and should be closed, + regardless of whether the test passed: + - - after the current test class, when declared on a - class with class mode set to AFTER_CLASS, - which is the default class mode - - - after each test method in the current test class, - when declared on a class with class mode set to - AFTER_EACH_TEST_METHOD - - - after the current test, when declared on a method - + + After the current test class, when declared on a class + with class mode set to AFTER_CLASS, which is + the default class mode. + + + + After each test method in the current test class, when + declared on a class with class mode set to + AFTER_EACH_TEST_METHOD. + + + + After the current test, when declared on a method. + - - Use this annotation if a test has modified the context - (for example, by replacing a bean definition). Subsequent tests - will be supplied a new context. - - @DirtiesContext may be used - as a class-level and method-level annotation within the same class. - In such scenarios, the ApplicationContext - will be marked as dirty after any such - annotated method as well as after the entire class. If the - ClassMode is set to - AFTER_EACH_TEST_METHOD, the context will be + + Use this annotation if a test has modified the context (for + example, by replacing a bean definition). Subsequent tests are + supplied a new context. + + + Limitations of + <interfacename>@DirtiesContext</interfacename> with JUnit + 3.8<!--JUnit 3.8 and earlier? Later? ONLY JUnit 3.8? Specify.--> + + In a JUnit 3.8 environment + @DirtiesContext is only supported + on methods and thus not at the class level. + + + You can use @DirtiesContext as + a class-level and method-level annotation within the same class. + In + such scenarios, the + ApplicationContext is marked as + dirty after any such annotated method as well + as after the entire class. If the ClassMode + is set to AFTER_EACH_TEST_METHOD, the context is marked dirty after each test method in the class. @DirtiesContext @@ -491,18 +499,11 @@ public void testProcessWhichDirtiesAppCtx() { // some logic that results in the Spring container being dirtied } - Whenever an application context is marked as - dirty, it will be removed from the testing - framework's cache and closed; thus the underlying Spring container will be - rebuilt for any subsequent test which requires a context with the + When an application context is marked + dirty, it is removed from the testing + framework's cache and closed; thus the underlying Spring container + is rebuilt for any subsequent test that requires a context with the same set of resource locations. - - - Limitations of <interfacename>@DirtiesContext</interfacename> with JUnit 3.8 - In a JUnit 3.8 environment @DirtiesContext - is only supported on methods and thus not at the class level. - - @@ -513,7 +514,7 @@ public void testProcessWhichDirtiesAppCtx() { TestExecutionListeners should be registered with a TestContextManager. Typically, @TestExecutionListeners - will be used in conjunction with + are used in conjunction with @ContextConfiguration. @ContextConfiguration @@ -522,9 +523,9 @@ public class CustomTestExecutionListenerTests { // class body... } - Note: @TestExecutionListeners - provides support for inherited listeners by - default. See the JavaDoc for an example and further details. + @TestExecutionListeners + supports inherited listeners by default. See + the JavaDoc for an example and further details. @@ -536,11 +537,10 @@ public class CustomTestExecutionListenerTests { PlatformTransactionManager that is to be used to drive transactions can be explicitly configured if the bean name of the desired PlatformTransactionManager is not - "transactionManager". In addition, the - defaultRollback flag can optionally be changed to - false. Typically, - @TransactionConfiguration will be - used in conjunction with + "transactionManager". In addition, you can change the + defaultRollback flag to false. + Typically, @TransactionConfiguration + is used in conjunction with @ContextConfiguration. @ContextConfiguration @@ -554,12 +554,12 @@ public class CustomConfiguredTransactionalTests { @Rollback - Indicates whether or not the transaction for the annotated - test method should be rolled back after the - test method has completed. If true, the - transaction will be rolled back; otherwise, the transaction will be - committed. Use @Rollback to override - the default rollback flag configured at the class level. + Indicates whether the transaction for the annotated test + method should be rolled back after the test + method has completed. If true, the transaction is + rolled back; otherwise, the transaction is committed. Use + @Rollback to override the default + rollback flag configured at the class level. @Rollback(false) @Test @@ -575,7 +575,7 @@ public void testProcessWithoutRollback() { Indicates that the annotated public void method should be executed before a transaction is started for test methods configured to run within a transaction - via the @Transactional + through the @Transactional annotation. @BeforeTransaction @@ -590,8 +590,8 @@ public void beforeTransaction() { Indicates that the annotated public void method should be executed after a transaction - has been ended for test methods configured to run within a - transaction via the @Transactional + has ended for test methods configured to run within a transaction + through the @Transactional annotation. @AfterTransaction @@ -616,19 +616,20 @@ public void testProcessWithoutTransaction() { @NotTransactional is deprecated - As of Spring 3.0, @NotTransactional - is deprecated in favor of moving the - non-transactional test + + As of Spring 3.0, + @NotTransactional is deprecated in + favor of moving the non-transactional test method to a separate (non-transactional) test class or to a @BeforeTransaction or - @AfterTransaction method. - As an alternative to annotating an entire class with - @Transactional consider - annotating individual methods with - @Transactional; - doing so allows a mix of transactional and non-transactional - methods in the same test class without the need for - using @NotTransactional. + @AfterTransaction method. As an + alternative to annotating an entire class with + @Transactional, consider annotating + individual methods with + @Transactional; doing so allows a + mix of transactional and non-transactional methods in the same + test class without the need for using + @NotTransactional. @@ -636,11 +637,12 @@ public void testProcessWithoutTransaction() { The following annotations are only supported - when used in conjunction with JUnit (i.e., with the SpringJUnit4ClassRunner or - the JUnit 3.8.2 - and JUnit 4.5+ - support classes. + the JUnit + 3.8.2 and JUnit 4.5+ support + classes. @@ -651,8 +653,8 @@ public void testProcessWithoutTransaction() { testing environment. If the configured ProfileValueSource returns a matching value for the provided name, - the test will be enabled. This annotation can be applied to an - entire class or individual methods. Class-level usage overrides + the test is enabled. This annotation can be applied to an entire + class or to individual methods. Class-level usage overrides method-level usage. @IfProfileValue(name="java.vendor", value="Sun Microsystems Inc.") @@ -661,11 +663,11 @@ public void testProcessWhichRunsOnlyOnSunJvm() { // some logic that should run only on Java VMs from Sun Microsystems } - Alternatively @IfProfileValue - may be configured with a list of values (with - OR semantics) to achieve TestNG-like support - for test groups in a JUnit environment. - Consider the following example: + Alternatively, you can configure + @IfProfileValue with a list of + values (with OR semantics) + to achieve TestNG-like support for test groups + in a JUnit environment. Consider the following example: @IfProfileValue(name="test-groups", values={"unit-tests", "integration-tests"}) @Test @@ -678,13 +680,13 @@ public void testProcessWhichRunsForUnitOrIntegrationTestGroups() { @ProfileValueSourceConfiguration - Class-level annotation which is used to specify what type of + Class-level annotation that specifies what type of ProfileValueSource to use when retrieving - profile values configured via the + profile values configured through the @IfProfileValue annotation. If @ProfileValueSourceConfiguration is not declared for a test, - SystemProfileValueSource will be used by + SystemProfileValueSource is used by default. @ProfileValueSourceConfiguration(CustomProfileValueSource.class) @@ -723,13 +725,12 @@ public void testProcessRainyDayScenario() { @Timed - Indicates that the annotated test method has to finish - execution in a specified time period (in milliseconds). If the text - execution time takes longer than the specified time period, the test - fails. + Indicates that the annotated test method must finish execution + in a specified time period (in milliseconds). If the text execution + time exceeds the specified time period, the test fails. - Note that the time period includes execution of the test - method itself, any repetitions of the test (see + The time period includes execution of the test method itself, + any repetitions of the test (see @Repeat), as well as any set up or tear down of the test fixture. @@ -743,15 +744,15 @@ public void testProcessWithOneSecondTimeout() { different semantics than JUnit 4's @Test(timeout=...) support. Specifically, due to the manner in which JUnit 4 handles test - execution timeouts (i.e., by executing the test method in a separate - Thread), + execution timeouts (that is, by executing the test method in a + separate Thread), @Test(timeout=...) applies to each iteration in the case of repetitions and preemptively fails the test if the test takes too long. Spring's @Timed, on the other hand, times the total test execution time (including all repetitions) and does not preemptively fail the test but rather - waits for the test to actually complete before failing. + waits for the test to complete before failing. @@ -762,10 +763,9 @@ public void testProcessWithOneSecondTimeout() { repeatedly. The number of times that the test method is to be executed is specified in the annotation. - Note that the scope of execution to be repeated includes - execution of the test method itself as well as any set - up or tear down of the test - fixture. + The scope of execution to be repeated includes execution of + the test method itself as well as any set up or + tear down of the test fixture. @Repeat(10) @Test @@ -828,18 +828,18 @@ public void testProcessRepeatedly() { The Spring TestContext Framework (located in the org.springframework.test.context package) provides - generic, annotation-driven unit and integration testing support that - is agnostic of the testing framework in use, for example JUnit 3.8.2, - JUnit 4.5+, TestNG 5.10, etc. The TestContext framework also places a + generic, annotation-driven unit and integration testing support that is + agnostic of the testing framework in use, whether JUnit 3.8.2, JUnit + 4.5+, TestNG 5.10, and so on. The TestContext framework also places a great deal of importance on convention over - configuration with reasonable defaults that can be - overridden via annotation-based configuration. + configuration with reasonable defaults that can be overridden + through annotation-based configuration. In addition to generic testing infrastructure, the TestContext framework provides explicit support for JUnit 3.8.2, JUnit 4.5+, and - TestNG 5.10 in the form of abstract support - classes. For JUnit 4.5+, the framework also provides a custom - Runner which allows one to write test + TestNG 5.10 in the form of abstract support classes. + For JUnit 4.5+, the framework also provides a custom + Runner that allows one to write test classes that are not required to extend a particular class hierarchy. @@ -865,31 +865,30 @@ public void testProcessRepeatedly() { TestExecutionListener interface. A TestContextManager is created on a per-test basis. The TestContextManager in turn manages a - TestContext which is responsible for holding - the context of the current test. The - TestContextManager is also responsible for - updating the state of the TestContext as the - test progresses and delegating to + TestContext that holds the context of the + current test. The TestContextManager also + updates the state of the TestContext as the + test progresses and delegates to TestExecutionListeners, which - instrument the actual test execution (e.g., providing dependency - injection, managing transactions, etc.). Consult the JavaDoc and the - Spring test suite for further information and examples of various + instrument the actual test execution, by providing dependency + injection, managing transactions, and so on. Consult the JavaDoc and + the Spring test suite for further information and examples of various configurations. - TestContext: encapsulates the context + TestContext: Encapsulates the context in which a test is executed, agnostic of the actual testing framework in use. - TestContextManager: the main entry + TestContextManager: The main entry point into the Spring TestContext Framework, - which is responsible for managing a single - TestContext and signaling events to all - registered TestExecutionListeners - at well defined test execution points: test instance preparation, + which manages a single TestContext and + signals events to all registered + TestExecutionListeners at + well-defined test execution points: test instance preparation, prior to any before methods of a particular testing framework, and after any after methods of a particular testing framework. @@ -897,28 +896,29 @@ public void testProcessRepeatedly() { TestExecutionListener: - defines a listener API for reacting to test + Defines a listener API for reacting to test execution events published by the TestContextManager with which the listener is registered. Spring provides three TestExecutionListener - implementations which are configured by default: - DependencyInjectionTestExecutionListener, - DirtiesContextTestExecutionListener, and - TransactionalTestExecutionListener, which - provide support for dependency injection of the test instance, - handling of the @DirtiesContext - annotation, and transactional test execution support with default - rollback semantics, respectively. + implementations that are configured by default: + DependencyInjectionTestExecutionListener, + DirtiesContextTestExecutionListener, and + TransactionalTestExecutionListener. + Respectively, they support dependency injection of the test + instance, handling of the + @DirtiesContext annotation, and + transactional test execution with default rollback + semantics. The following three sections explain how to configure the - TestContext framework via annotations and - provide working examples of how to actually write unit and integration - tests with the framework. + TestContext framework through annotations and + provide working examples of how to write unit and integration tests + with the framework.
@@ -929,13 +929,13 @@ public void testProcessRepeatedly() { Each TestContext provides context management and caching support for the test instance for which it is responsible. Test instances do not automatically receive access to the - configured ApplicationContext; however, if a + configured ApplicationContext. However, if a test class implements the ApplicationContextAware interface, a - reference to the ApplicationContext will be - supplied to the test instance (provided the - DependencyInjectionTestExecutionListener has - been configured, which is the default). Note that + reference to the ApplicationContext is supplied + to the test instance, if the + DependencyInjectionTestExecutionListener is + configured, which is the default. AbstractJUnit38SpringContextTests, AbstractJUnit4SpringContextTests, and AbstractTestNGSpringContextTests already @@ -947,9 +947,9 @@ public void testProcessRepeatedly() { As an alternative to implementing the ApplicationContextAware interface, - your test class can have its application context injected via the - @Autowired annotation on either a - field or setter method, for example: + you can inject the application context for your test class through + the @Autowired annotation on either a + field or setter method. For example: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @@ -963,21 +963,21 @@ public class MyTest { In contrast to the now deprecated JUnit 3.8 legacy class - hierarchy, test classes which use the TestContext framework do not - need to override any protected instance methods to + hierarchy, test classes that use the TestContext framework do not need + to override any protected instance methods to configure their application context. Rather, configuration is achieved merely by declaring the @ContextConfiguration annotation at the - class level. If your test class does not explicitly declare any + class level. If your test class does not explicitly declare application context resource locations, the - configured ContextLoader will determine - how and whether or not to load a context from a default set of - locations. For example, GenericXmlContextLoader - - which is the default ContextLoader - - will generate a default location based on the name of the test class. - If your class is named com.example.MyTest, - GenericXmlContextLoader will load your - application context from + configured ContextLoader determines how + and whether to load a context from a default set of locations. For + example, GenericXmlContextLoader , which is the + default ContextLoader, generates a + default location based on the name of the test class. If your class is + named com.example.MyTest, + GenericXmlContextLoader loads your application + context from "classpath:/com/example/MyTest-context.xml". package com.example; @@ -989,16 +989,16 @@ public class MyTest { // class body... } - If the default location does not suit your needs, you are free - to explicitly configure the locations attribute of - @ContextConfiguration (see code listing - below) with an array containing the resource locations of XML - configuration metadata (assuming an XML-capable - ContextLoader has been configured) - - typically on the classpath - used to configure the application. This - will be the same, or nearly the same, as the list of configuration - locations specified in web.xml or other deployment - configuration. As an alternative you may choose to implement and + If the default location does not suit your needs, you can + configure explicitly the locations attribute of + @ContextConfiguration with an array + that contains the resource locations of XML configuration metadata + (assuming an XML-capable ContextLoader + has been configured) - typically in the classpath + - used to configure the application. (See the following code example.) + This location will be the same, or nearly the same, as the list of + configuration locations specified in web.xml or + other deployment configuration. Alternatively, you can implement and configure your own custom ContextLoader. @@ -1011,29 +1011,28 @@ public class MyTest { } @ContextConfiguration supports an - alias for the locations attribute via the standard - value attribute. Thus, if you do not need to - configure a custom ContextLoader, you - can omit the declaration of the locations attribute - name and declare the resource locations using the shorthand format - demonstrated in the following example. + alias for the locations attribute through the + standard value attribute. Thus, if you do not need + to configure a custom ContextLoader, + you can omit the declaration of the locations + attribute name and declare the resource locations by using the + shorthand format demonstrated in the following example. @ContextConfiguration also supports a - boolean inheritLocations attribute which denotes - whether or not resource locations from superclasses should be + boolean inheritLocations attribute that denotes + whether resource locations from superclasses should be inherited. The default value is - true, which means that an annotated class will - inherit the resource locations defined by an - annotated superclass. Specifically, the resource locations for an - annotated class will be appended to the list of resource locations - defined by an annotated superclass. Thus, subclasses have the option - of extending the list of resource locations. In - the following example, the + true, which means that an annotated class inherits + the resource locations defined by an annotated superclass. + Specifically, the resource locations for an annotated class are + appended to the list of resource locations defined by an annotated + superclass. Thus, subclasses have the option of + extending the list of resource locations. In the + following example, the ApplicationContext for - ExtendedTest will be loaded from - "/base-context.xml" and - "/extended-context.xml", in that order. Beans defined in - "/extended-context.xml" may therefore override those defined in - "/base-context.xml". + ExtendedTest is loaded from "/base-context.xml" + and "/extended-context.xml", in that + order. Beans defined in "/extended-context.xml" may therefore override + those defined in "/base-context.xml". @RunWith(SpringJUnit4ClassRunner.class) // ApplicationContext will be loaded from "/base-context.xml" in the root of the classpath @@ -1051,22 +1050,22 @@ public class ExtendedTest extends BaseTest { If inheritLocations is set to false, the resource locations for the annotated - class will shadow and effectively replace any - resource locations defined by a superclass. + class shadows and effectively replaces any resource locations defined + by a superclass. By default, once loaded, the configured - ApplicationContext will be reused for - each test. Thus the setup cost will be incurred only once (per test - fixture), and subsequent test execution will be much faster. In the - unlikely case that a test may dirty the - application context, requiring reloading - for example, by changing a - bean definition or the state of an application object - you may - annotate your test method with + ApplicationContext is reused for each + test. Thus the setup cost is incurred only once (per test fixture), + and subsequent test execution is much faster. In the unlikely case + that a test dirties (modifies) + the application context, requiring reloading -- for example, by + changing a bean definition or the state of an application object -- + you can annotate your test method with @DirtiesContext (assuming DirtiesContextTestExecutionListener has been configured, which is the default) to cause the test fixture to reload the configurations and rebuild the application context before - executing the next test. + executing the next test. @@ -1075,25 +1074,25 @@ public class ExtendedTest extends BaseTest { Dependency Injection of test fixtures When you configure the - DependencyInjectionTestExecutionListener - - which is configured by default - via the - @TestExecutionListeners annotation, the - dependencies of your test instances will be + DependencyInjectionTestExecutionListener -- + which is configured by default through the + @TestExecutionListeners annotation-- + the dependencies of your test instances are injected from beans in the application context - you configured via - @ContextConfiguration by Setter - Injection, Field Injection, or both, depending on which annotations + you configured through + @ContextConfiguration by setter + injection, field injection, or both, depending on which annotations you choose and whether you place them on setter methods or fields. For consistency with the annotation support introduced in Spring 2.5, you - may choose either Spring's @Autowired - annotation or the @Resource annotation - from JSR 250. The semantics for both are consistent throughout the - Spring Framework. For example, if you prefer @Autowired annotation + or the @Resource annotation from JSR + 250. The semantics for both are consistent throughout the Spring + Framework. For example, if you prefer autowiring by type, annotate your setter methods or fields with - @Autowired. On the other hand, if you - prefer to have your dependencies injected by - name, annotate your setter methods or fields with + @Autowired. If you prefer to have your + dependencies injected by name, annotate your + setter methods or fields with @Resource. @@ -1103,7 +1102,7 @@ public class ExtendedTest extends BaseTest { effect for test classes. - Since @Autowired performs Because @Autowired performs autowiring by type, if you have multiple bean definitions of the same type, you cannot rely on this approach for those particular @@ -1111,13 +1110,13 @@ public class ExtendedTest extends BaseTest { @Resource for injection by name. Alternatively, if your test class has access to its ApplicationContext, you can perform an explicit - lookup using (for example) a call to + lookup by using (for example) a call to applicationContext.getBean("titleDao"). A third option is to use @Autowired in conjunction with @Qualifier. - If you don't want dependency injection applied to your test - instances, simply don't annotate any fields or setter methods with + If you do not want dependency injection applied to your test + instances, simply do not annotate fields or setter methods with @Autowired or @Resource. Alternatively, you can disable dependency injection altogether by explicitly configuring your @@ -1126,27 +1125,26 @@ public class ExtendedTest extends BaseTest { DependencyInjectionTestExecutionListener.class from the list of listeners. - Consider the scenario where we have a class, - HibernateTitleDao (as outlined in the Goals section). First, let's look - at a JUnit 4 based implementation of the test class itself which - uses @Autowired for field injection (we - will look at the application context configuration after all sample - code listings). Note: The dependency injection behavior in - the following code listings is not in any way specific to JUnit 4. - The same DI techniques can be used in conjunction with any testing - framework. + Consider the scenario of a class, + HibernateTitleDao, as outlined in the Goals section. (We will look at + the application context configuration after all sample code listings.) + A JUnit 4-based implementation of the test class itself uses + @Autowired for field injection. - - Static imports for assertions - The following examples make calls to static - assertion methods such as assertNotNull() - but without prepending the call with - "Assert.". In such cases you should assume - that the method has been properly imported via - an import static declaration which is - simply not shown in the example. - + + The dependency injection behavior in the following code + listings is not in any way specific to JUnit 4. The same DI + techniques can be used in conjunction with any testing + framework. + + The following examples make calls to static assertion methods + such as assertNotNull() but without prepending + the call with Assert. In such cases, assume that + the method was properly imported through an import + static declaration that is not shown in the + example. + @RunWith(SpringJUnit4ClassRunner.class) // specifies the Spring configuration to load for this test fixture @@ -1166,7 +1164,7 @@ public final class HibernateTitleDaoTests { - Alternatively, we can configure the class to use + Alternatively, you can configure the class to use @Autowired for setter injection. @RunWith(SpringJUnit4ClassRunner.class) @@ -1191,8 +1189,8 @@ public final class HibernateTitleDaoTests { - Now let's take a look at an example using - @Resource for field injection. + Here is an example of @Resource + for field injection. @RunWith(SpringJUnit4ClassRunner.class) // specifies the Spring configuration to load for this test fixture @@ -1212,8 +1210,8 @@ public final class HibernateTitleDaoTests { - Finally, here is an example using - @Resource for setter injection. + Here is an example of @Resource + for setter injection. @RunWith(SpringJUnit4ClassRunner.class) // specifies the Spring configuration to load for this test fixture @@ -1237,9 +1235,10 @@ public final class HibernateTitleDaoTests { - The above code listings use the same XML context file referenced - by the @ContextConfiguration annotation - (i.e., "daos.xml") which looks like this: + The preceding code listings use the same XML context file + referenced by the @ContextConfiguration + annotation (that is, daos.xml), which looks like + this: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" @@ -1253,7 +1252,8 @@ public final class HibernateTitleDaoTests { <property name="sessionFactory" ref="sessionFactory"/> </bean> - <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> + <bean id="sessionFactory" + class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <!-- dependencies elided for clarity --> </bean> @@ -1262,10 +1262,10 @@ public final class HibernateTitleDaoTests { If you are extending from a Spring-provided test base class that happens to use @Autowired on one - of its setters methods, you might have multiple beans of the - affected type defined in your application context: e.g. multiple + of its setter methods, you might have multiple beans of the affected + type defined in your application context: for example, multiple DataSource beans. In such a case, you - may override the setter and use the + can override the setter and use the @Qualifier annotation to indicate a specific target bean as follows: @@ -1288,15 +1288,15 @@ public final class HibernateTitleDaoTests { also point to a specific bean by name there (as shown above, assuming that "myDataSource" is the bean id). If there is only one DataSource bean to begin with, then - the qualifier will simply not have any effect - independent from the - bean name of that single matching bean. + the qualifier does not have any effect, independent from the bean + name of that single matching bean. Alternatively, consider using the - @Resource annotation on such an - overridden setter methods, defining the target bean name explicitly - - with no type matching semantics. Note that this always points to a - bean with that specific name, no matter whether there is one or more - beans of the given type. + @Resource annotation on such + overridden setter methods, defining the target bean name explicitly, + with no type matching semantics. Note that this always + points to a bean with that specific name, no matter whether there is + one or more beans of the given type. // ... @@ -1317,76 +1317,76 @@ public final class HibernateTitleDaoTests { In the TestContext framework, transactions are managed by the TransactionalTestExecutionListener, which is - configured via the + configured through the @TestExecutionListeners annotation by default, even if you do not explicitly declare @TestExecutionListeners on your test class. To enable support for transactions, however, you must provide a PlatformTransactionManager bean in the - application context loaded via + application context loaded by @ContextConfiguration semantics. In addition, you must declare @Transactional either at the class or method level. - For class-level transaction configuration (i.e., setting the + For class-level transaction configuration (that is, setting the bean name for the transaction manager and the default rollback flag), see the @TransactionConfiguration entry in the annotation support section. - If transactions are not enabled for the - entire test class, methods may be explicitly annotated with - @Transactional. To control whether - or not a transaction should commit for a particular test method, you - may use the @Rollback annotation to - override the class-level default rollback setting. + If transactions are not enabled for the entire test class, you + can annotate methods explicitly with + @Transactional. To control whether a + transaction should commit for a particular test method, you can use + the @Rollback annotation to override + the class-level default rollback setting. - Note that AbstractTransactionalJUnit38SpringContextTests, AbstractTransactionalJUnit4SpringContextTests, and AbstractTransactionalTestNGSpringContextTests - are pre-configured for transactional support at the class level. + are preconfigured for transactional support at the class level. - You will occasionally find that you need to execute certain code - before or after a transactional test method but outside the - transactional context, for example to verify the initial database - state prior to execution of your test or to verify expected - transactional commit behavior after test execution (e.g., if the test - was configured not to roll back the transaction). + Occasionally you need to execute certain code before or after a + transactional test method but outside the transactional context, for + example, to verify the initial database state prior to execution of + your test or to verify expected transactional commit behavior after + test execution (for example, if the test was configured not to roll + back the transaction). TransactionalTestExecutionListener supports the @BeforeTransaction and @AfterTransaction annotations exactly for such scenarios. Simply annotate any public void method in your test class with one of these annotations, and the - TransactionalTestExecutionListener will ensure - that your before transaction method or - after transaction method is executed at the - appropriate time. + TransactionalTestExecutionListener ensures that + your before transaction method or after + transaction method is executed at the appropriate + time. - Any before methods (e.g., methods + Any before methods (for example, methods annotated with JUnit 4's @Before) and any after - methods (e.g., methods annotated with JUnit 4's @After) - will be executed within a - transaction. In addition, methods annotated with + methods (such as methods annotated with JUnit 4's @After) + are executed within a transaction. + In addition, methods annotated with @BeforeTransaction or - @AfterTransaction will naturally not - be executed for tests annotated with - @NotTransactional. Note, however, - that @NotTransactional is - deprecated as of Spring 3.0. + @AfterTransaction are naturally not + executed for tests annotated with + @NotTransactional. However, + @NotTransactional is deprecated as of + Spring 3.0. The following JUnit 4 based example displays a fictitious - integration testing scenario highlighting several of the - transaction-related annotations. Consult the annotation support - section of the reference manual for further information and - configuration examples. + section of the reference manual for + further information and configuration examples. @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @@ -1425,17 +1425,17 @@ public class FictitiousTransactionalTest { Avoid false positives when testing ORM code - When testing code involving an ORM framework such as JPA - or Hibernate, it is a good practice to - flush the underlying session within test - methods which update the state of the session. Failing to flush - the ORM framework's underlying session can lead to - false positives: your test may pass, but - the same code will throw an exception in a live, production - environment. In the following Hibernate-based example test case, - we have two methods: one which demonstrates a false positive - and one which correctly exposes the results of flushing the - session. + + When you test code involving an ORM framework such as JPA or + Hibernate, flush the underlying session within + test methods which update the state of the + session. Failing to flush the ORM framework's underlying session can + produce false positives: your test may pass, + but the same code throws an exception in a live, production + environment. In the following Hibernate-based example test case, one + method demonstrates a false positive and the other method correctly + exposes the results of flushing the session. // ... @@ -1458,7 +1458,6 @@ public void updateWithSessionFlush() { // ... - @@ -1475,29 +1474,31 @@ public void updateWithSessionFlush() { - AbstractJUnit38SpringContextTests: + AbstractJUnit38SpringContextTests: + Abstract TestCase that integrates the + Spring TestContext Framework with explicit + ApplicationContext testing support in a + JUnit 3.8 environment. When you extend the + AbstractJUnit38SpringContextTests class, + you need access to the following protected + instance variables: - applicationContext: use this to - perform explicit bean lookups or to test the state of the - context as a whole. + applicationContext: Perform + explicit bean lookups or test the state of the context as a + whole. - AbstractTransactionalJUnit38SpringContextTests: - - Abstract transactional extension of + AbstractTransactionalJUnit38SpringContextTests: + Abstract transactional extension of AbstractJUnit38SpringContextTests that also adds some convenience functionality for JDBC access. Expects a javax.sql.DataSource bean and a @@ -1505,27 +1506,30 @@ public void updateWithSessionFlush() { to be defined in the ApplicationContext. When you extend the AbstractTransactionalJUnit38SpringContextTests - class you will have access to the following + class, you will have access to the following protected instance variables: - applicationContext: inherited from + applicationContext: Inherited from the AbstractJUnit38SpringContextTests - superclass. Use this to perform explicit bean lookups or to - test the state of the context as a whole. + superclass. Use this variable to perform explicit bean + lookups or to test the state of the context as a + whole. - simpleJdbcTemplate: useful for - querying to confirm state. For example, you might query - before and after testing application code that creates an - object and persists 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 the same transaction.) You will - need to tell your ORM tool to 'flush' its changes for this - to work correctly, for example using the - flush() method on Hibernate's + simpleJdbcTemplate: Useful for + querying to confirm state. For example, use an ORM tool to + query before and after testing application code that creates + an object and persists it, to + verify that the data appears in the database. (Spring + ensures that the query runs in the scope of the same + transaction.) You need to tell your ORM tool to 'flush' its + changes for this to work correctly by, for example, using + the flush() method on Hibernate's Session interface. @@ -1542,61 +1546,57 @@ public void updateWithSessionFlush() { - AbstractJUnit4SpringContextTests: - - Abstract base test class which integrates the - Spring TestContext Framework with explicit + AbstractJUnit4SpringContextTests: + Abstract base test class that integrates the Spring + TestContext Framework with explicit ApplicationContext testing support in a JUnit 4.5+ environment. When you extend - AbstractJUnit4SpringContextTests you will - have access to the following protected - instance variables: + AbstractJUnit4SpringContextTests, you can + access the following protected instance + variable: - applicationContext: use this to - perform explicit bean lookups or to test the state of the - context as a whole. + applicationContext: Perform + explicit bean lookups or test the state of the context as a + whole. - AbstractTransactionalJUnit4SpringContextTests: - - Abstract transactional extension of + AbstractTransactionalJUnit4SpringContextTests: + Abstract transactional extension of AbstractJUnit4SpringContextTests that also adds some convenience functionality for JDBC access. Expects a javax.sql.DataSource bean and a PlatformTransactionManager bean - to be defined in the - ApplicationContext. - - When you extend + to be defined in the ApplicationContext. + When you extend AbstractTransactionalJUnit4SpringContextTests - you will have access to the following - protected instance variables: + you can access the following protected + instance variables: - applicationContext: inherited from + applicationContext: Inherited from the AbstractJUnit4SpringContextTests - superclass. Use this to perform explicit bean lookups or to - test the state of the context as a whole. + superclass. Perform explicit bean lookups or test the state + of the context as a whole. - simpleJdbcTemplate: useful for - querying to confirm state. For example, you might query - before and after testing application code that creates an - object and persists 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 the same transaction.) You will - need to tell your ORM tool to 'flush' its changes for this - to work correctly, for example using the - flush() method on Hibernate's + simpleJdbcTemplate: Useful for + querying to confirm state. For example, use an ORM tool to + query before and after testing application code that creates + an object and persists it, to verify that the data appears + in the database. (Spring + ensures that the query runs in the scope of the same + transaction.) You need to tell your ORM tool to 'flush' its + changes for this to work correctly by, for example, using + the flush() method on Hibernate's Session interface. @@ -1604,15 +1604,15 @@ public void updateWithSessionFlush() { - These classes serve only as a convenience for extension. If - you do not wish for your test classes to be tied to a - Spring-specific class hierarchy - for example, if you wish to - directly extend the class you are testing - you may configure your - own custom test classes by using + These classes are a convenience for extension. If you do not + want your test classes to be tied to a Spring-specific class + hierarchy -- for example, if you want to extend directly the class + you are testing -- you can configure your own custom test classes + by using @RunWith(SpringJUnit4ClassRunner.class), @ContextConfiguration, - @TestExecutionListeners, - etc. + @TestExecutionListeners, and so + on. @@ -1620,21 +1620,19 @@ public void updateWithSessionFlush() { Custom JUnit 4.5+ Runner The Spring TestContext Framework offers - full integration with JUnit 4.5+ via a custom runner (tested on + full integration with JUnit 4.5+ through a custom runner (tested on JUnit 4.5, 4.6, and 4.7). By annotating test classes with @Runwith(SpringJUnit4ClassRunner.class), developers can implement standard JUnit 4.5+ unit and integration tests and simultaneously reap the benefits of the TestContext framework such as support for loading application contexts, dependency injection of test instances, transactional test method - execution, etc. The following code listing displays the minimal - requirements for configuring a test class to run with the custom - Spring Runner. Note that - @TestExecutionListeners has been - configured with an empty list in order to disable the default - listeners, which would otherwise require that an - ApplicationContext be configured via - @ContextConfiguration. + execution, and so on. The following code listing displays the + minimal requirements for configuring a test class to run with the + custom Spring Runner. @TestExecutionListeners is configured with an + empty list in order to disable the default listeners, which + otherwise would require an ApplicationContext to be configured + through @ContextConfiguration. @RunWith(SpringJUnit4ClassRunner.class) @TestExecutionListeners({}) @@ -1655,76 +1653,71 @@ public class SimpleTest { - AbstractTestNGSpringContextTests: - - Abstract base test class which integrates the - Spring TestContext Framework with explicit + AbstractTestNGSpringContextTests: + Abstract base test class that integrates the Spring + TestContext Framework with explicit ApplicationContext testing support in a TestNG environment. When you extend - AbstractTestNGSpringContextTests you will - have access to the following protected - instance variables: + AbstractTestNGSpringContextTests you can + access the following protected instance + variable: - applicationContext: use this to - perform explicit bean lookups or to test the state of the - context as a whole. + applicationContext: Perform + explicit bean lookups or test the state of the context as a + whole. - AbstractTransactionalTestNGSpringContextTests: - - Abstract transactional extension of + AbstractTransactionalTestNGSpringContextTests: + Abstract transactional extension of AbstractTestNGSpringContextTests that adds some convenience functionality for JDBC access. Expects a javax.sql.DataSource bean and a PlatformTransactionManager bean - to be defined in the - ApplicationContext. - - When you extend - AbstractTransactionalTestNGSpringContextTests - you will have access to the following - protected instance variables: + to be defined in the ApplicationContext. + When you extend + AbstractTransactionalTestNGSpringContextTests, + you can access the following protected + instance variables: - applicationContext: inherited from + applicationContext: Inherited from the AbstractTestNGSpringContextTests - superclass. Use this to perform explicit bean lookups or to - test the state of the context as a whole. + superclass. Perform explicit bean lookups or test the state + of the context as a whole. - simpleJdbcTemplate: useful for - querying to confirm state. For example, you might query - before and after testing application code that creates an - object and persists 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 the same transaction.) You will - need to tell your ORM tool to 'flush' its changes for this - to work correctly, for example using the - flush() method on Hibernate's - Session interface. + simpleJdbcTemplate: Useful for + querying to confirm state. For example, use an ORM tool to + query before and after testing application code that creates + an object and persists it, to verify that the data appears + in the database. (Spring ensures that the query runs in the + scope of the same transaction.) You need to tell your ORM + tool to 'flush' its changes for this to work correctly by, + for example, using the flush() + method on Hibernate's Session + interface. - These classes serve only as a convenience for extension. If - you do not wish for your test classes to be tied to a - Spring-specific class hierarchy - for example, if you wish to - directly extend the class you are testing - you may configure your - own custom test classes by using - @ContextConfiguration, - @TestExecutionListeners, etc. and - by manually instrumenting your test class with a + These classes are a convenience for extension. If you do not + want your test classes to be tied to a Spring-specific class + hierarchy--for example, if you want to directly extend the class + you are testing--you can configure your own custom test classes by + using @ContextConfiguration, + @TestExecutionListeners, and so on, + and by manually instrumenting your test class with a TestContextManager. See the source code of AbstractTestNGSpringContextTests for an example of how to instrument your test class. @@ -1778,75 +1771,75 @@ public abstract class AbstractClinicTests extends Abstract This test case extends the AbstractTransactionalJUnit4SpringContextTests class, from which it inherits configuration for Dependency Injection - (via the + (through the DependencyInjectionTestExecutionListener) and - transactional behavior (via the + transactional behavior (through the TransactionalTestExecutionListener). The clinic instance variable - the - application object being tested - is set by Dependency Injection via - @Autowired semantics. + application object being tested - is set by Dependency Injection + through @Autowired semantics. The testGetVets() method illustrates - how the inherited countRowsInTable() method - can be used to easily verify the number of rows in a given table, - thus testing correct behavior of the application code being tested. - This allows for stronger tests and lessens dependency on the exact - test data. For example, you can add additional rows in the database - without breaking tests. + how you can use the inherited + countRowsInTable() method to easily verify + the number of rows in a given table, thus testing correct behavior + of the application code being tested. This allows for stronger tests + and lessens dependency on the exact test data. For example, you can + add additional rows in the database without breaking tests. - Like many integration tests using a database, most of the + Like many integration tests that use a database, most of the tests in AbstractClinicTests depend on a minimum amount of data already in the database before the test cases - run. You might, however, choose to populate the database in your + run. You might, however, choose to populate the database in your test cases also - again, within the same transaction. - The PetClinic application supports three data access technologies - - JDBC, Hibernate, and JPA. By declaring + The PetClinic application supports three data access technologies: + JDBC, Hibernate, and JPA. By declaring @ContextConfiguration without any specific resource locations, the AbstractClinicTests class will have its application context loaded from the default location, - "AbstractClinicTests-context.xml", which declares a + AbstractClinicTests-context.xml, which declares a common DataSource. Subclasses specify additional - context locations which must declare a + context locations that must declare a PlatformTransactionManager and a concrete implementation of Clinic. For example, the Hibernate implementation of the PetClinic tests - contains the following implementation. Note that for this example, + contains the following implementation. For this example, HibernateClinicTests does not contain a single line of code: we only need to declare @ContextConfiguration, and the tests are - inherited from AbstractClinicTests. Since + inherited from AbstractClinicTests. Because @ContextConfiguration is declared without any specific resource locations, the Spring TestContext - Framework will load an application context from all the beans - defined in "AbstractClinicTests-context.xml" (i.e., + Framework loads an application context from all the beans + defined in AbstractClinicTests-context.xml (that is, the inherited locations) and - "HibernateClinicTests-context.xml", with - "HibernateClinicTests-context.xml" possibly - overriding beans defined in - "AbstractClinicTests-context.xml". + HibernateClinicTests-context.xml, with + HibernateClinicTests-context.xml possibly overriding + beans defined in + AbstractClinicTests-context.xml. @ContextConfiguration public class HibernateClinicTests extends AbstractClinicTests { } As you can see in the PetClinic application, the Spring - configuration is split across multiple files. As is typical of large - scale applications, configuration locations will often be specified in a - common base class for all application-specific integration tests. Such a - base class may also add useful instance variables - populated by - Dependency Injection, naturally - such as a + configuration is split across multiple files. As + is typical of large-scale applications, configuration locations are + often specified in a common base class for all application-specific + integration tests. Such a base class may also add useful instance + variables--populated by Dependency Injection, naturally--such as a HibernateTemplate, in the case of an application using Hibernate. @@ -1865,7 +1858,7 @@ public class HibernateClinicTests extends AbstractClinicTests { } and DataSourceTransactionManager or HibernateTransactionManager for them. You can factor out this variant behavior into a single XML file, having the - choice between application server and 'local' configuration separated + choice between application server and a 'local' configuration separated from all other configuration, which will not vary between the test and production environments. In addition, it is advisable to use properties files for connection settings: see the PetClinic application for an @@ -1878,61 +1871,62 @@ public class HibernateClinicTests extends AbstractClinicTests { }
Further Resources - This section contains links to further resources about testing in - general. + Consult the following resources for more information about + testing: - JUnit: the Spring - Framework's unit and integration test suite is written using JUnit 3.8.2 + JUnit: The Spring + Framework's unit and integration test suite, written with JUnit 3.8.2 and JUnit 4.7 as the testing framework. - TestNG: a testing + TestNG: A testing framework inspired by JUnit 3.8 with added support for Java 5 annotations, test groups, data-driven testing, distributed testing, - etc. + and so on. MockObjects.com: a website + url="http://www.mockobjects.com/">MockObjects.com: Web site dedicated to mock objects, a technique for improving the design of - code within Test-Driven Development. + code within test-driven development. "Mock - Objects": article at Wikipedia. + Objects": Article in Wikipedia. - EasyMock: the - Spring Framework uses EasyMock extensively in its test suite. + EasyMock: Used + extensively by the Spring Framework in its test suite. - JMock: a library that + JMock: Library that supports test-driven development of Java code with mock objects. - Mockito: a Java mock - library based on the test spy + Mockito: Java mock + library based on the test spy pattern. - DbUnit: a + DbUnit: JUnit extension (also usable with Ant and Maven) targeted for database-driven projects that, among other things, puts your database into a known state between test runs. - Grinder: a + Grinder: Java load testing framework.