The document provides an overview of testing features introduced in Spring 3.1, focusing on the Spring TestContext framework, which simplifies integration testing for Spring-based applications, and new support for testing with @Configuration classes and environment profiles. It details various testing annotations, integration scenarios, and example test cases, emphasizing the importance of unit and integration testing with proper configuration. Additionally, it discusses the Spring MVC test support capabilities, allowing for comprehensive controller testing without the need for a running servlet container.
Spring 3.1 and MVC Testing Support overview, goal to learn testing features including Spring MVC Test Support.
Presentation agenda covering Spring TestContext Framework, MVC Test Support, and testing methodologies.
Features of the Spring TestContext Framework introduced in versions 2.5 and revised in 3.1, emphasizing annotation-driven and convention-based testing.
Details on Spring's unit and integration testing capabilities, including managing ApplicationContexts and using test annotations.
Critical components of TestContext like TestContextManager and TestExecutionListener, detailing their roles in testing.
Introduction of features for testing with @Configuration classes and environment profiles, including SmartContextLoader.
How to implement tests utilizing @Configuration classes instead of XML, showcasing updated functionalities.
Combining @Configuration classes with traditional XML configuration for holistic application setups.
Using @ActiveProfiles to enable specific bean definitions during tests, with examples using XML and Java configurations.
Code examples showcasing how to configure and test services using @Configuration classes and profile management.
Enhancements to caching mechanisms in the TestContext Framework for improved performance during tests.
Introduction to testing Spring MVC components, utilizing MockMvc to interact with controllers without a servlet container.
Steps to configure MockMvc for testing Spring MVC applications, including setting expectations and debugging.
Client-side testing strategies using MockRestServiceServer and project availability for Spring MVC test.
Open floor for questions with contact details for presenters and resources for further reading.
Spring 3.1 andMVC
Testing Support
Sam Brannen
Swiftmind
Rossen Stoyanchev
SpringSource, VMware
SpringOne 2GX
October 28, 2011
2.
Sam Brannen
Senior SoftwareConsultant @ Swiftmind
Java developer with 13+ years' experience
Spring Framework Core Developer
Lead author of Spring in a Nutshell
Previous SpringSource dm Server™ developer
Presenter on Spring, Java, OSGi, and testing
3.
Rossen Stoyanchev
Staff EngineerSpringSource, VMware
Spring MVC, Spring Web Flow committer
Teach and consult, Spring Projects
Spring Web course author
NYC area
4.
Goals of the
Presentation
Gain an overview of testing features
in Spring 3.1
Learn about the new Spring MVC
Test Support project
Spring & UnitTesting
POJO-based programming model
Program to interfaces
IoC / Dependency Injection
Out-of-container testability
Testing mocks/stubs for various APIs: Servlet,
Portlet, JNDI
General purpose testing utilities
ReflectionTestUtils
ModelAndViewAssert
15.
Spring & IntegrationTesting
ApplicationContext management & caching
Dependency injection of test instances
Transactional test management
with default rollback semantics
SimpleJdbcTestUtils
JUnit 3.8 support classes are deprecated as of
Spring 3.0/3.1
16.
Spring Test Annotations
ApplicationContexts
@ContextConfiguration, @DirtiesContext
@TestExecutionListeners
Dependency Injection
@Autowired, @Qualifier, @Inject, …
Transactions
@Transactional, @TransactionConfiguration, @Rollback,
@BeforeTransaction, @AfterTransaction
17.
Spring JUnit Annotations
Testing Profiles
groups, not bean definition
profiles
@IfProfileValue,
@ProfileValueSourceConfiguration
JUnit extensions
@Timed, @Repeat
18.
Using the TestContext
Framework
Use the SpringJUnit4ClassRunner for
JUnit 4.5+
Instrument test class with
TestContextManager for TestNG
Extend one of the base classes
Abstract(Transactional)[JUnit4|TestNG]Spri
19.
Example: @POJO TestClass
public class OrderServiceTests {
@Test
public void testOrderService() { … }
}
20.
Example: @POJO TestClass
@RunWith(SpringJUnit4ClassRunner.class)
public class OrderServiceTests {
@Test
public void testOrderService() { … }
}
21.
Example: @POJO TestClass
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class OrderServiceTests {
@Test
public void testOrderService() { … }
}
22.
Example: @POJO TestClass
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration // defaults to
// OrderServiceTests-context.xml in same package
public class OrderServiceTests {
@Test
public void testOrderService() { … }
}
23.
Example: @POJO TestClass
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration // defaults to
// OrderServiceTests-context.xml in same package
public class OrderServiceTests {
@Autowired
private OrderService orderService;
@Test
public void testOrderService() { … }
}
24.
Example: @POJO TestClass
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration // defaults to
// OrderServiceTests-context.xml in same package
@Transactional
public class OrderServiceTests {
@Autowired
private OrderService orderService;
@Test
public void testOrderService() { … }
}
25.
Example: @POJO TestClass
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration // defaults to
// OrderServiceTests-context.xml in same package
@Transactional
public class OrderServiceTests {
@Autowired
private OrderService orderService;
@BeforeTransaction
public void verifyInitialDatabaseState() { … }
@Test
public void testOrderService() { … }
}
26.
Example: @POJO TestClass
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration // defaults to
// OrderServiceTests-context.xml in same package
@Transactional
public class OrderServiceTests {
@Autowired
private OrderService orderService;
@BeforeTransaction
public void verifyInitialDatabaseState() { … }
@Before
public void setUpTestDataWithinTransaction() { … }
@Test
public void testOrderService() { … }
}
TestExecutionListener SPI
Reacts to test execution events
Receives reference to current TestContext
Out of the box:
DependencyInjectionTestExecutionListener
DirtiesContextTestExecutionListener
TransactionalTestExecutionListener
ContextLoader SPI
Strategy for loading application contexts
from resource locations
Out of the box:
GenericXmlContextLoader
GenericPropertiesContextLoader
@Configuration + XML
Q: How can we combine
@Configuration classes with XML
config?
A: Choose one as the entry point.
That's how it works in production
anyway
70.
Importing Configuration
InXML:
include @Configuration classes via
component scanning
or define them as normal Spring
beans
In an @Configuration class:
use @ImportResource to import XML
config files
@ActiveProfiles
Toactivate bean definition profiles in tests...
Annotate a test class with
@ActiveProfiles
Supply a list of profiles to be
activated for the test
Can be used with @Configuration
classes and XML config
TransferServiceConfig.java
@Configuration
public class TransferServiceConfig{
@Autowired DataSource dataSource;
@Bean
public TransferService transferService() {
return new DefaultTransferService(accountRepository(),
feePolicy());
}
@Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository(dataSource);
}
@Bean
public FeePolicy feePolicy() {
return new ZeroFeePolicy();
}
}
83.
}
JndiDataConfig.java
@Configuration
@Profile("production")
public class JndiDataConfig {
@Bean
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource)
ctx.lookup("java:comp/env/jdbc/datasource");
}
}
New Key GenerationAlgorithm
The context cache key generation algorithm has been updated to include...
locations (from @ContextConfiguration)
classes (from @ContextConfiguration)
contextLoader (from @ContextConfiguration)
activeProfiles (from @ActiveProfiles)
96.
Summary
The Spring TestContextFramework simplifies
integration testing of Spring-based
applications
Spring 3.1 provides first-class testing support
for:
@Configuration classes
Environment profiles
See the Testing with @Configuration Classes
and Profiles blog for further insight
@Controller
@RequestMapping("/accounts")
public class AccountController{
// ...
@ModelAttribute
public Account getAccount(String number) {
return this.accountManager.getAccount(number);
}
@RequestMapping(method = RequestMethod.POST)
public String save(@Valid Account account,
BindingResult result) {
if (result.hasErrors()) {
return "accounts/edit";
}
this.accountManager.saveOrUpdate(account);
return "redirect:accounts";
}
}
100.
Unit Test?
Create controller instance
Mock or stub services & repositories
101.
Example
@Test
public void testSave(){
Account account = new Account();
BindingResult result =
new BeanPropertyBindingResult(account, "account");
}
102.
Example
@Test
public void testSave(){
Account account = new Account();
BindingResult result =
new BeanPropertyBindingResult(account, "account");
AccountManager mgr = createMock(AccountManager.class);
mgr.saveOrUpdate(account);
replay(mgr);
}
103.
Example
@Test
public void testSave(){
Account account = new Account();
BindingResult result =
new BeanPropertyBindingResult(account, "account");
AccountManager mgr = createMock(AccountManager.class);
mgr.saveOrUpdate(account);
replay(mgr);
AccountController contrlr = new AccountController(mgr);
String view = contrlr.save(account, result);
}
104.
Example
@Test
public void testSave(){
Account account = new Account();
BindingResult result =
new BeanPropertyBindingResult(account, "account");
AccountManager mgr = createMock(AccountManager.class);
mgr.saveOrUpdate(account);
replay(mgr);
AccountController contrlr = new AccountController(mgr);
String view = contrlr.save(account, result);
assertEquals("redirect:accounts", view);
verify(mgr);
}
105.
Example With Failure
@Test
publicvoid testSave() {
Account account = new Account();
BindingResult result =
new BeanPropertyBindingResult(account, "account");
result.reject("error.code", "default message")
}
106.
Example With Failure
@Test
publicvoid testSave() {
Account account = new Account();
BindingResult result =
new BeanPropertyBindingResult(account, "account");
result.reject("error.code", "default message")
AccountManager mgr = createMock(AccountManager.class);
replay(mgr);
}
107.
Example With Failure
@Test
publicvoid testSave() {
Account account = new Account();
BindingResult result =
new BeanPropertyBindingResult(account, "account");
result.reject("error.code", "default message")
AccountManager mgr = createMock(AccountManager.class);
replay(mgr);
AccountController contrlr = new AccountController(mgr);
String view = contrlr.save(account, result);
assertEquals("accounts/edit", view);
verify(mgr);
}
108.
Not Fully Tested
Request mappings
Binding errors
Type conversion
Etc.
the only wayto verify...
Client-side behavior
Interaction with other server instances
Redis, Rabbit, etc.
114.
We'd also liketo...
Test controllers once!
Fully & quickly
Execute tests often
115.
In summary...
We can'treplace the need for end-to-
end tests
But we can minimize errors
Have confidence in @MVC code
During end-to-end tests
116.
Spring MVC Test
Built on spring-test
No Servlet container
Drives Spring MVC infrastructure
Both server & client-side test support
(i.e. RestTemplate code)
Inspired by spring-ws-test
117.
The Approach
Re-use controller test fixtures
I.e. mocked services & repositories
Invoke @Controller classes through
@MVC infrastructure
Under the Covers
Mockrequest/response from spring-test
DispatcherServlet replacement
Multiple ways to initialize MVC
infrastructure
Save results for expectations
Resources for SpringMVC Test
Project Home:
https://github.com/SpringSource/spring-test-mvc
Sample Tests:
org.springframework.test.web.server.samples
143.
Resources for CoreSpring
Spring Framework:
http://www.springsource.org/spring-core
Reference Manual: Spring 3.1 RC1
Forums: http://forum.springframework.org
JIRA: https://jira.springsource.org
Spring in a Nutshell … available in 2012