This session will give attendees an overview of the new testing features in Spring 3.1 as well the new Spring MVC test support. Sam Brannen will demonstrate how to use the Spring TestContext Framework to write integration tests for Java-based Spring configuration using @Configuration classes. He'll then compare and contrast this approach with XML-based configuration and follow up with a discussion of the new testing support for bean definition profiles. Next, Rossen Stoyanchev will show attendees how testing server-side code with annotated controllers and client-side code with the RestTemplate just got a whole lot easier with the new Spring MVC test support. Come to this session to see these new Spring testing features in action and learn how you can get involved in the Spring MVC Test Support project.
Top 10 Most Downloaded Games on Play Store in 2024
Spring 3.1 and MVC Testing Support
1. Spring 3.1 and MVC
Testing Support
Sam Brannen
Swiftmind
Rossen Stoyanchev
SpringSource, VMware
SpringOne 2GX
October 28, 2011
2. Sam Brannen
Senior Software Consultant @ 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 Engineer SpringSource, 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
6. Show of Hands...
JUnit / TestNG
Spring 2.5 / 3.0 / 3.1
Integration testing with Spring
Spring TestContext Framework
Spring MVC
Spring MVC Test Support
14. Spring & Unit Testing
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 & Integration Testing
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
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 Test Class
public class OrderServiceTests {
@Test
public void testOrderService() { … }
}
20. Example: @POJO Test Class
@RunWith(SpringJUnit4ClassRunner.class)
public class OrderServiceTests {
@Test
public void testOrderService() { … }
}
21. Example: @POJO Test Class
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class OrderServiceTests {
@Test
public void testOrderService() { … }
}
22. Example: @POJO Test Class
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration // defaults to
// OrderServiceTests-context.xml in same package
public class OrderServiceTests {
@Test
public void testOrderService() { … }
}
23. Example: @POJO Test Class
@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 Test Class
@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 Test Class
@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 Test Class
@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() { … }
}
30. TestExecutionListener SPI
Reacts to test execution events
Receives reference to current TestContext
Out of the box:
DependencyInjectionTestExecutionListener
DirtiesContextTestExecutionListener
TransactionalTestExecutionListener
34. ContextLoader SPI
Strategy for loading application contexts
from resource locations
Out of the box:
GenericXmlContextLoader
GenericPropertiesContextLoader
69. @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
In XML:
include @Configuration classes via
component scanning
or define them as normal Spring
beans
In an @Configuration class:
use @ImportResource to import XML
config files
72. @ActiveProfiles
To activate 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
81. And now an example with
@Configuration classes
82. 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");
}
}
95. New Key Generation Algorithm
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 TestContext Framework 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
99. @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
public void testSave() {
Account account = new Account();
BindingResult result =
new BeanPropertyBindingResult(account, "account");
result.reject("error.code", "default message")
}
106. Example With Failure
@Test
public void 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
public void 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.
113. the only way to verify...
Client-side behavior
Interaction with other server instances
Redis, Rabbit, etc.
114. We'd also like to...
Test controllers once!
Fully & quickly
Execute tests often
115. In summary...
We can't replace 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
119. Under the Covers
Mock request/response from spring-test
DispatcherServlet replacement
Multiple ways to initialize MVC
infrastructure
Save results for expectations
124. About Manual Setup
MVC components instantiated directly
Not looked up in Spring context
Focused, readable tests
But must verify MVC config separately
125. TestContext Framework Example
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
locations={"/org/example/servlet-context.xml"})
public class TestContextTests {
@Autowired
private WebApplicationContext wac;
@Before
public void setup() {
MockMvc mockMvc =
MockMvcBuilders.webApplicationContextSetup(this.wac)
.build();
}
}
126. TestContext Framework
Caches loaded Spring configuration
Potentially across all tests!
142. Resources for Spring MVC Test
Project Home:
https://github.com/SpringSource/spring-test-mvc
Sample Tests:
org.springframework.test.web.server.samples
143. Resources for Core Spring
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