133
Spring 3.1 and MVC Testing Support Sam Brannen Swiftmind 4Developers 18 April 2012

Spring 3.1 and MVC Testing Support - 4Developers

Embed Size (px)

DESCRIPTION

Please note that this presentation is an abridged version of the one given by Rossen Stoyanchev and me at SpringOne 2GX 2012. 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, attendees will see 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.

Citation preview

Page 1: Spring 3.1 and MVC Testing Support - 4Developers

Spring 3.1 and MVCTesting Support

Sam BrannenSwiftmind

4Developers18 April 2012

Page 2: Spring 3.1 and MVC Testing Support - 4Developers

Sam BrannenSpring & Java Consultant @ Swiftmind

Developing Java for over 14 years

Spring Framework Core Committer

Spring Trainer

Lead author of “Spring in a Nutshell”

Twitter: @sam_brannen

Page 3: Spring 3.1 and MVC Testing Support - 4Developers

Goals of thePresentation

Gain an overview of testing featuresin Spring 3.1

Learn about the new Spring MVCTest Support project

Page 4: Spring 3.1 and MVC Testing Support - 4Developers

AgendaSpring TestContext Framework

Testing with @Configuration Classes

Testing with Environment Profiles

Spring MVC Test Support

Q&A

Page 5: Spring 3.1 and MVC Testing Support - 4Developers

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

Page 6: Spring 3.1 and MVC Testing Support - 4Developers

Spring TestContextFramework

Page 7: Spring 3.1 and MVC Testing Support - 4Developers

Introduced in Spring 2.5

Page 8: Spring 3.1 and MVC Testing Support - 4Developers

Revised in Spring 3.1

Page 9: Spring 3.1 and MVC Testing Support - 4Developers

Unit and integration testing

Page 10: Spring 3.1 and MVC Testing Support - 4Developers

Annotation-driven

Page 11: Spring 3.1 and MVC Testing Support - 4Developers

Convention over Configuration

Page 12: Spring 3.1 and MVC Testing Support - 4Developers

JUnit & TestNG

Page 13: Spring 3.1 and MVC Testing Support - 4Developers

Spring & Unit TestingPOJO-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 utilitiesReflectionTestUtilsModelAndViewAssert

Page 14: Spring 3.1 and MVC Testing Support - 4Developers

Spring & Integration TestingApplicationContext management & caching

Dependency injection of test instances

Transactional test managementwith default rollback semantics

SimpleJdbcTestUtils

JUnit 3.8 support classes are deprecated as ofSpring 3.0/3.1

Page 15: Spring 3.1 and MVC Testing Support - 4Developers

Spring Test AnnotationsApplication Contexts

@ContextConfiguration, @DirtiesContext

@TestExecutionListeners

Dependency Injection@Autowired, @Qualifier, @Inject, …

Transactions@Transactional, @TransactionConfiguration, @Rollback,@BeforeTransaction, @AfterTransaction

Page 16: Spring 3.1 and MVC Testing Support - 4Developers

Using the TestContextFramework

Use the SpringJUnit4ClassRunner forJUnit 4.5+

Instrument test class withTestContextManager for TestNG

Extend one of the base classesAbstract(Transactional)[JUnit4|TestNG]SpringContextTests

Page 17: Spring 3.1 and MVC Testing Support - 4Developers

Example: @POJO Test Class

public class OrderServiceTests {

@Test public void testOrderService() { … }}

Page 18: Spring 3.1 and MVC Testing Support - 4Developers

Example: @POJO Test Class@RunWith(SpringJUnit4ClassRunner.class)

public class OrderServiceTests {

@Test public void testOrderService() { … }}

Page 19: Spring 3.1 and MVC Testing Support - 4Developers

Example: @POJO Test Class@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration

public class OrderServiceTests {

@Test public void testOrderService() { … }}

Page 20: Spring 3.1 and MVC Testing Support - 4Developers

Example: @POJO Test Class@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration // defaults to// OrderServiceTests-context.xml in same packagepublic class OrderServiceTests {

@Test public void testOrderService() { … }}

Page 21: Spring 3.1 and MVC Testing Support - 4Developers

Example: @POJO Test Class@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration // defaults to// OrderServiceTests-context.xml in same packagepublic class OrderServiceTests { @Autowired private OrderService orderService;

@Test public void testOrderService() { … }}

Page 22: Spring 3.1 and MVC Testing Support - 4Developers

Example: @POJO Test Class@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration // defaults to// OrderServiceTests-context.xml in same package@Transactionalpublic class OrderServiceTests { @Autowired private OrderService orderService;

@Test public void testOrderService() { … }}

Page 23: Spring 3.1 and MVC Testing Support - 4Developers

Example: @POJO Test Class@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration // defaults to// OrderServiceTests-context.xml in same package@Transactionalpublic class OrderServiceTests { @Autowired private OrderService orderService; @BeforeTransaction public void verifyInitialDatabaseState() { … }

@Test public void testOrderService() { … }}

Page 24: Spring 3.1 and MVC Testing Support - 4Developers

Example: @POJO Test Class@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration // defaults to// OrderServiceTests-context.xml in same package@Transactionalpublic class OrderServiceTests { @Autowired private OrderService orderService; @BeforeTransaction public void verifyInitialDatabaseState() { … } @Before public void setUpTestDataWithinTransaction() { … } @Test public void testOrderService() { … }}

Page 25: Spring 3.1 and MVC Testing Support - 4Developers

Core Components

Page 26: Spring 3.1 and MVC Testing Support - 4Developers

TestContextTracks context for current test

Delegates to a ContextLoader

Caches ApplicationContext

Page 27: Spring 3.1 and MVC Testing Support - 4Developers

TestContextManagerManages the TestContext

Signals events to listeners...

Page 28: Spring 3.1 and MVC Testing Support - 4Developers

TestExecutionListener SPIReacts to test execution events

Receives reference to current TestContext

Out of the box:DependencyInjectionTestExecutionListenerDirtiesContextTestExecutionListenerTransactionalTestExecutionListener

Page 29: Spring 3.1 and MVC Testing Support - 4Developers

ContextLoader SPIStrategy for loading application contexts

from resource locations

Page 30: Spring 3.1 and MVC Testing Support - 4Developers

Putting it all together

Page 31: Spring 3.1 and MVC Testing Support - 4Developers

New in Spring 3.1

Page 32: Spring 3.1 and MVC Testing Support - 4Developers

Support for ...

Page 33: Spring 3.1 and MVC Testing Support - 4Developers

testing with @Configuration classes

Page 34: Spring 3.1 and MVC Testing Support - 4Developers

and

Page 35: Spring 3.1 and MVC Testing Support - 4Developers

testing with environment profiles

Page 36: Spring 3.1 and MVC Testing Support - 4Developers

made possible by ...

Page 37: Spring 3.1 and MVC Testing Support - 4Developers

SmartContextLoader

Page 38: Spring 3.1 and MVC Testing Support - 4Developers

AnnotationConfigContextLoader

Page 39: Spring 3.1 and MVC Testing Support - 4Developers

DelegatingSmartContextLoader

Page 40: Spring 3.1 and MVC Testing Support - 4Developers

updated context cache key generation

Page 41: Spring 3.1 and MVC Testing Support - 4Developers

SmartContextLoader SPISupersedes ContextLoader

Strategy for loading applicationcontexts

From @Configuration classes orresource locations

Supports environment profiles

Page 42: Spring 3.1 and MVC Testing Support - 4Developers

ImplementationsGenericXmlContextLoader

GenericPropertiesContextLoader

AnnotationConfigContextLoader

DelegatingSmartContextLoader

Page 43: Spring 3.1 and MVC Testing Support - 4Developers

ContextLoader 3.1

Page 44: Spring 3.1 and MVC Testing Support - 4Developers

Testing with@Configuration Classes

Page 45: Spring 3.1 and MVC Testing Support - 4Developers

@ContextConfigurationaccepts a new classes attribute...

Page 46: Spring 3.1 and MVC Testing Support - 4Developers

@ContextConfiguration( classes={DataAccessConfig.class, ServiceConfig.class})

Page 47: Spring 3.1 and MVC Testing Support - 4Developers

First, a review with XML config forcomparison...

Page 48: Spring 3.1 and MVC Testing Support - 4Developers

OrderServiceTest-context.xml

<?xml version="1.0" encoding="UTF-8"?><beans ...> <!-- will be injected into OrderServiceTest --> <bean id="orderService" class="com.example.OrderServiceImpl"> <!-- set properties, etc. --> </bean> <!-- other beans --></beans>

Page 49: Spring 3.1 and MVC Testing Support - 4Developers

OrderServiceTest.java

package com.example;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfigurationpublic class OrderServiceTest { @Autowired private OrderService orderService; @Test public void testOrderService() { // test the orderService }}

Page 50: Spring 3.1 and MVC Testing Support - 4Developers

Let's rework that example to use a@Configuration class and the newAnnotationConfigContextLoader...

Page 51: Spring 3.1 and MVC Testing Support - 4Developers

OrderServiceTest.java

@RunWith(SpringJUnit4ClassRunner.class)

public class OrderServiceTest {

@Autowired private OrderService orderService; // @Test methods ...}

Page 52: Spring 3.1 and MVC Testing Support - 4Developers

OrderServiceTest.java

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration( loader=AnnotationConfigContextLoader.class)public class OrderServiceTest {

@Autowired private OrderService orderService; // @Test methods ...}

Page 53: Spring 3.1 and MVC Testing Support - 4Developers

OrderServiceTest.java

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfigurationpublic class OrderServiceTest {

@Autowired private OrderService orderService; // @Test methods ...}

Page 54: Spring 3.1 and MVC Testing Support - 4Developers

OrderServiceTest.java

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfigurationpublic class OrderServiceTest { @Configuration static class Config {

} @Autowired private OrderService orderService; // @Test methods ...}

Page 55: Spring 3.1 and MVC Testing Support - 4Developers

OrderServiceTest.java

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfigurationpublic class OrderServiceTest { @Configuration static class Config { @Bean // will be injected into OrderServiceTest public OrderService orderService() { OrderService orderService = new OrderServiceImpl(); // set properties, etc. return orderService; } } @Autowired private OrderService orderService; // @Test methods ...}

Page 56: Spring 3.1 and MVC Testing Support - 4Developers

What's changed?No XML

Bean definitions are converted toJava

using @Configuration and @Bean

Otherwise, the test remainsunchanged

Page 57: Spring 3.1 and MVC Testing Support - 4Developers

But what if we don't want a staticinner @Configuration class?

Page 58: Spring 3.1 and MVC Testing Support - 4Developers

Just externalize the config...

Page 59: Spring 3.1 and MVC Testing Support - 4Developers

OrderServiceConfig.java

@Configurationpublic class OrderServiceConfig { @Bean // will be injected into OrderServiceTest public OrderService orderService() { OrderService orderService = new OrderServiceImpl(); // set properties, etc. return orderService; }}

Page 60: Spring 3.1 and MVC Testing Support - 4Developers

And reference the config classes in@ContextConfiguration...

Page 61: Spring 3.1 and MVC Testing Support - 4Developers

OrderServiceConfig.java

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(classes=OrderServiceConfig.class)public class OrderServiceTest { @Autowired private OrderService orderService; @Test public void testOrderService() { // test the orderService }}

Page 62: Spring 3.1 and MVC Testing Support - 4Developers

@Configuration + XMLQ: How can we combine@Configuration classes with XMLconfig?

A: Choose one as the entry point.

That's how it works in productionanyway

Page 63: Spring 3.1 and MVC Testing Support - 4Developers

Importing ConfigurationIn XML:

include @Configuration classes viacomponent scanningor define them as normal Springbeans

In an @Configuration class:use @ImportResource to import XMLconfig files

Page 64: Spring 3.1 and MVC Testing Support - 4Developers

Testing withEnvironment Profiles

Page 65: Spring 3.1 and MVC Testing Support - 4Developers

@ActiveProfilesTo activate bean definition profiles in tests...

Annotate a test class with@ActiveProfiles

Supply a list of profiles to beactivated for the test

Can be used with @Configurationclasses and XML config

Page 66: Spring 3.1 and MVC Testing Support - 4Developers

Let's look at an example with XMLconfig...

Page 67: Spring 3.1 and MVC Testing Support - 4Developers

app-config.xml (1/2)

<beans ... > <bean id="transferService" class="com.example.DefaultTransferService"> <constructor-arg ref="accountRepository"/> <constructor-arg ref="feePolicy"/> </bean> <bean id="accountRepository" class="com.example.JdbcAccountRepository"> <constructor-arg ref="dataSource"/> </bean> <bean id="feePolicy" class="com.example.ZeroFeePolicy"/> <!-- dataSource --></beans>

Page 68: Spring 3.1 and MVC Testing Support - 4Developers

app-config.xml (2/2)

<beans ... > <!-- transferService, accountRepository, feePolicy -->

</beans>

Page 69: Spring 3.1 and MVC Testing Support - 4Developers

app-config.xml (2/2)

<beans ... > <!-- transferService, accountRepository, feePolicy --> <beans profile="production"> <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/> </beans>

</beans>

Page 70: Spring 3.1 and MVC Testing Support - 4Developers

app-config.xml (2/2)

<beans ... > <!-- transferService, accountRepository, feePolicy --> <beans profile="production"> <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/> </beans> <beans profile="dev"> <jdbc:embedded-database id="dataSource"> <jdbc:script location="classpath:schema.sql"/> <jdbc:script location="classpath:test-data.sql"/> </jdbc:embedded-database> </beans></beans>

Page 71: Spring 3.1 and MVC Testing Support - 4Developers

TransferServiceTest.java

@RunWith(SpringJUnit4ClassRunner.class)

public class TransferServiceTest { @Autowired private TransferService transferService; @Test public void testTransferService() { // test the transferService }}

Page 72: Spring 3.1 and MVC Testing Support - 4Developers

TransferServiceTest.java

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("/app-config.xml")public class TransferServiceTest { @Autowired private TransferService transferService; @Test public void testTransferService() { // test the transferService }}

Page 73: Spring 3.1 and MVC Testing Support - 4Developers

TransferServiceTest.java

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("/app-config.xml")@ActiveProfiles("dev")public class TransferServiceTest { @Autowired private TransferService transferService; @Test public void testTransferService() { // test the transferService }}

Page 74: Spring 3.1 and MVC Testing Support - 4Developers

And now an example with@Configuration classes

Page 75: Spring 3.1 and MVC Testing Support - 4Developers

TransferServiceConfig.java

@Configurationpublic 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(); }}

Page 76: Spring 3.1 and MVC Testing Support - 4Developers

}

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"); }}

Page 77: Spring 3.1 and MVC Testing Support - 4Developers

StandaloneDataConfig.java

@Configuration@Profile("dev")public class StandaloneDataConfig { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.HSQL) .addScript("classpath:schema.sql") .addScript("classpath:test-data.sql") .build(); }}

Page 78: Spring 3.1 and MVC Testing Support - 4Developers

And finally the test class...

Page 79: Spring 3.1 and MVC Testing Support - 4Developers

TransferServiceTest.java

package com.bank.service;@RunWith(SpringJUnit4ClassRunner.class)

public class TransferServiceTest { @Autowired private TransferService transferService; @Test public void testTransferService() { // test the transferService }}

Page 80: Spring 3.1 and MVC Testing Support - 4Developers

TransferServiceTest.java

package com.bank.service;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration( classes={ TransferServiceConfig.class, StandaloneDataConfig.class, JndiDataConfig.class})public class TransferServiceTest { @Autowired private TransferService transferService; @Test public void testTransferService() { // test the transferService }}

Page 81: Spring 3.1 and MVC Testing Support - 4Developers

TransferServiceTest.java

package com.bank.service;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration( classes={ TransferServiceConfig.class, StandaloneDataConfig.class, JndiDataConfig.class})@ActiveProfiles("dev")public class TransferServiceTest { @Autowired private TransferService transferService; @Test public void testTransferService() { // test the transferService }}

Page 82: Spring 3.1 and MVC Testing Support - 4Developers

Active Profile Inheritance@ActiveProfiles supports inheritance as well

Via the inheritProfiles attribute

See Javadoc for an example

Page 83: Spring 3.1 and MVC Testing Support - 4Developers

ApplicationContextCaching

Page 84: Spring 3.1 and MVC Testing Support - 4Developers

Until Spring 3.1

Page 85: Spring 3.1 and MVC Testing Support - 4Developers

application contexts were cached

Page 86: Spring 3.1 and MVC Testing Support - 4Developers

but using only resource locations forthe key.

Page 87: Spring 3.1 and MVC Testing Support - 4Developers

Now there are differentrequirements...

Page 88: Spring 3.1 and MVC Testing Support - 4Developers

New Key Generation AlgorithmThe context cache key generation algorithm has been updated to include...

locations (from @ContextConfiguration)

classes (from @ContextConfiguration)

contextLoader (from @ContextConfiguration)

activeProfiles (from @ActiveProfiles)

Page 89: Spring 3.1 and MVC Testing Support - 4Developers

SummaryThe Spring TestContext Framework simplifiesintegration testing of Spring-basedapplications

Spring 3.1 provides first-class testing supportfor:

@Configuration classesEnvironment profiles

See the Testing with @Configuration Classesand Profiles blog for further insight

Page 90: Spring 3.1 and MVC Testing Support - 4Developers

Spring MVC TestSupport

Page 91: Spring 3.1 and MVC Testing Support - 4Developers

How Do You Test an@Controller?

Page 92: Spring 3.1 and MVC Testing Support - 4Developers

@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"; }}

Page 93: Spring 3.1 and MVC Testing Support - 4Developers

Unit Test?Create controller instance

Mock or stub services & repositories

Page 94: Spring 3.1 and MVC Testing Support - 4Developers

Example@Testpublic void testSave() { Account account = new Account(); BindingResult result = new BeanPropertyBindingResult(account, "account");

}

Page 95: Spring 3.1 and MVC Testing Support - 4Developers

Example@Testpublic void testSave() { Account account = new Account(); BindingResult result = new BeanPropertyBindingResult(account, "account"); AccountManager mgr = createMock(AccountManager.class); mgr.saveOrUpdate(account); replay(mgr);

}

Page 96: Spring 3.1 and MVC Testing Support - 4Developers

Example@Testpublic 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);

}

Page 97: Spring 3.1 and MVC Testing Support - 4Developers

Example@Testpublic 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);}

Page 98: Spring 3.1 and MVC Testing Support - 4Developers

Example With Failure@Testpublic void testSave() { Account account = new Account(); BindingResult result = new BeanPropertyBindingResult(account, "account"); result.reject("error.code", "default message")

}

Page 99: Spring 3.1 and MVC Testing Support - 4Developers

Example With Failure@Testpublic 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);

}

Page 100: Spring 3.1 and MVC Testing Support - 4Developers

Example With Failure@Testpublic 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);}

Page 101: Spring 3.1 and MVC Testing Support - 4Developers

Not Fully TestedRequest mappings?

Binding errors?

Type conversion?

etc.

Page 102: Spring 3.1 and MVC Testing Support - 4Developers

Integration Test?Selenium

JWebUnit

etc.

Page 103: Spring 3.1 and MVC Testing Support - 4Developers

But that requires...A running servlet container

More time to execute

More effort to maintain

Server is a black box

Page 104: Spring 3.1 and MVC Testing Support - 4Developers

And actually...

Page 105: Spring 3.1 and MVC Testing Support - 4Developers

it's an end-to-end test

Page 106: Spring 3.1 and MVC Testing Support - 4Developers

and the only way toverify...

Client-side behavior

Interaction with other server instances

Redis, Rabbit, etc.

Page 107: Spring 3.1 and MVC Testing Support - 4Developers

Ideally we'd like to...Test controllers once!

Fully & quickly

Execute tests often

Page 108: Spring 3.1 and MVC Testing Support - 4Developers

In summary...We can't replace the need for end-to-

end tests.

But we can minimize errors

and gain confidence in @MVC code

during end-to-end tests

Page 109: Spring 3.1 and MVC Testing Support - 4Developers

Spring MVC TestBuilt 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

Page 110: Spring 3.1 and MVC Testing Support - 4Developers

The ApproachRe-use controller test fixtures

i.e. mocked services & repositories

Invoke @Controller classes through@MVC infrastructure

Page 111: Spring 3.1 and MVC Testing Support - 4Developers

ExampleString contextLoc = "classpath:appContext.xml";String warDir = "src/main/webapp";MockMvc mockMvc = xmlConfigSetup(contextLoc) .configureWebAppRootDir(warDir, false) .build();mockMvc.perform(post("/persons")) .andExpect(response().status().isOk()) .andExpect(response().forwardedUrl("/add.jsp")) .andExpect(model().size(1)) .andExpect(model().hasAttributes("person"));

Page 112: Spring 3.1 and MVC Testing Support - 4Developers

Under the CoversMock request/response from spring-test

DispatcherServlet replacement

Multiple ways to initialize MVCinfrastructure

Save results for expectations

Page 113: Spring 3.1 and MVC Testing Support - 4Developers

Ways to Initialize MVCInfrastructure

Page 114: Spring 3.1 and MVC Testing Support - 4Developers

From Existing XML Config// XML configMockMvc mockMvc = xmlConfigSetup("classpath:appContext.xml") .activateProfiles(..) .configureWebAppRootDir(warDir, false) .build();

Page 115: Spring 3.1 and MVC Testing Support - 4Developers

From Existing Java Config// Java configMockMvc mockMvc = annotationConfigSetup(WebConfig.class) .activateProfiles(..) .configureWebAppRootDir(warDir, false) .build();

Page 116: Spring 3.1 and MVC Testing Support - 4Developers

Manually MockMvc mockMvc = standaloneSetup(new PersonController()) .setMessageConverters(..) .setValidator(..) .setConversionService(..) .addInterceptors(..) .setViewResolvers(..) .setLocaleResolver(..) .build();

Page 117: Spring 3.1 and MVC Testing Support - 4Developers

TestContext Framework Example@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("/org/example/servlet-context.xml")public class TestContextTests { @Autowired private WebApplicationContext wac; @Before public void setup() { MockMvc mockMvc = MockMvcBuilders.webApplicationContextSetup(this.wac) .build(); }}

Page 118: Spring 3.1 and MVC Testing Support - 4Developers

TestContext FrameworkCaches loaded Spring configuration

Potentially across all tests!

Page 119: Spring 3.1 and MVC Testing Support - 4Developers

However...WebApplicationContext is not yet

supported

To be supported in Spring 3.2

Page 120: Spring 3.1 and MVC Testing Support - 4Developers

How to Use Spring MVCTest

Page 121: Spring 3.1 and MVC Testing Support - 4Developers

Step 1Add static imports

MockMvcBuilders.*

MockMvcRequestBuilders.*

MockMvcResultActions.*

Page 122: Spring 3.1 and MVC Testing Support - 4Developers

Easy to remember...MockMvc*

Page 123: Spring 3.1 and MVC Testing Support - 4Developers

Step 2Initialize MVC infrastructure

String contextLoc = "classpath:appContext.xml";String warDir = "src/main/webapp";MockMvc mockMvc = xmlConfigSetup("classpath:appContext.xml") .configureWebAppRootDir(warDir, false) .build()

// ...

Page 124: Spring 3.1 and MVC Testing Support - 4Developers

Step 3Build Request

String contextLoc = "classpath:appContext.xml";String warDir = "src/main/webapp";MockMvc mockMvc = xmlConfigSetup("classpath:appContext.xml") .configureWebAppRootDir(warDir, false) .build()mockMvc.perform(get("/").accept(MediaType.APPLICATION_XML))

// ...

Page 125: Spring 3.1 and MVC Testing Support - 4Developers

Step 4Add Expectations

String contextLoc = "classpath:appContext.xml";String warDir = "src/main/webapp";MockMvc mockMvc = xmlConfigSetup("classpath:appContext.xml") .configureWebAppRootDir(warDir, false) .build()mockMvc.perform(get("/").accept(MediaType.APPLICATION_XML)) .andExpect(response().status().isOk()) .andExpect(response().contentType(MediaType)) .andExpect(response().content().xpath(String).exists()) .andExpect(response().redirectedUrl(String)) .andExpect(model().hasAttributes(String...));

// ...

Page 126: Spring 3.1 and MVC Testing Support - 4Developers

Step 5Debug

String contextLoc = "classpath:appContext.xml";String warDir = "src/main/webapp";MockMvc mockMvc = xmlConfigSetup("classpath:appContext.xml") .configureWebAppRootDir(warDir, false) .build()mockMvc.perform(get("/").accept(MediaType.APPLICATION_XML)) .andPrint(toConsole());

// ...

Page 127: Spring 3.1 and MVC Testing Support - 4Developers

Client-Side ExampleRestTemplate restTemplate = ... ;MockRestServiceServer.createServer(restTemplate) .expect(requestTo(String)) .andExpect(method(HttpMethod)) .andExpect(body(String)) .andExpect(headerContains(String, String)) .andRespond(withResponse(String, HttpHeaders));

Page 128: Spring 3.1 and MVC Testing Support - 4Developers

Project Availabilitygithub.com/SpringSource/spring-test-mvc

Request for feedback!

Send comments

Pull requests

Page 129: Spring 3.1 and MVC Testing Support - 4Developers

In Closing ...

Page 130: Spring 3.1 and MVC Testing Support - 4Developers

This PresentationSource:https://github.com/rstoyanchev/spring-31-and-mvc-testing-support

Slides:http://rstoyanchev.github.com/spring-31-and-mvc-test

Page 131: Spring 3.1 and MVC Testing Support - 4Developers

Resources for Spring MVC TestProject Home:https://github.com/SpringSource/spring-test-mvc

Sample Tests:org.springframework.test.web.server.samples

Page 132: Spring 3.1 and MVC Testing Support - 4Developers

Resources for Core SpringSpring Framework:http://www.springsource.org/spring-core

Reference Manual: Spring 3.1.x

Forums: http://forum.springframework.org

JIRA: https://jira.springsource.org

Spring in a Nutshell … available in 2012

Page 133: Spring 3.1 and MVC Testing Support - 4Developers

Q&A

Sam BrannenWeb: Swiftmind.com

Twitter: @sam_brannenSlideshare: sbrannen