56
Testing Spring MVC and REST Web Applications Sam Brannen @sam_brannen Spring eXchange | London, England | 15 November 2013

Testing Spring MVC and REST Web Applications

Embed Size (px)

Citation preview

Page 1: Testing Spring MVC and REST Web Applications

Testing Spring MVC and REST Web Applications Sam Brannen @sam_brannen

Spring eXchange | London, England | 15 November 2013

Page 2: Testing Spring MVC and REST Web Applications

2

Sam Brannen

•  Spring and Java Consultant @ Swiftmind

•  Java Developer for over 15 years

•  Spring Framework Core Committer since 2007

•  Spring Trainer •  Presenter on Spring, Java, OSGi, and testing

Page 3: Testing Spring MVC and REST Web Applications

3

Swiftmind

Your experts for Enterprise Java Areas of expertise •  Spring * •  Java EE •  OSGi •  Agile Methodologies •  Software Engineering Best Practices

Where you find us •  Zurich, Switzerland •  @swiftmind •  http://www.swiftmind.com

Page 4: Testing Spring MVC and REST Web Applications

4

A Show of Hands…

Page 5: Testing Spring MVC and REST Web Applications

5

Agenda

•  Spring TestContext Framework Updates

•  Spring MVC Test Framework

•  Q & A

Page 6: Testing Spring MVC and REST Web Applications

6

Spring TestContext Framework Updates

Page 7: Testing Spring MVC and REST Web Applications

7

What’s New in the Spring TCF?

•  Upgraded to JUnit 4.11 and TestNG 6.5.2

•  Loading a WebApplicationContext

•  Testing request- and session-scoped beans

•  Support for ApplicationContextInitializer

•  Loading context hierarchies (3.2.2)

•  Meta-annotation support for tests (4.0)

Page 8: Testing Spring MVC and REST Web Applications

8

Loading a WebApplicationContext

Q: How do you tell the TestContext Framework to load a WebApplicationContext?

A: Just annotate your test class with @WebAppConfiguration!

Page 9: Testing Spring MVC and REST Web Applications

9

@WebAppConfiguration

•  Denotes that the context should be a WebApplicationContext

•  Configures the resource path for the web app –  Used by MockServletContext –  Defaults to “src/main/webapp” –  Paths are file-system folders, relative to the project

root, not class path resources –  The classpath: prefix is also supported

Page 10: Testing Spring MVC and REST Web Applications

10

@WAC – Default Values

Page 11: Testing Spring MVC and REST Web Applications

11

@WAC – Default Resource Types

Page 12: Testing Spring MVC and REST Web Applications

12

@WAC – Overrides

Page 13: Testing Spring MVC and REST Web Applications

13

ServletTestExecutionListener

•  Sets up default thread-local state via RequestContextHolder before each test method

•  Creates: –  MockHttpServletRequest –  MockHttpServletResponse –  ServletWebRequest

•  Ensures that the MockHttpServletResponse and ServletWebRequest can be injected into the test instance

•  Cleans up thread-local state after each test method

Page 14: Testing Spring MVC and REST Web Applications

14

Example: Injecting Mocks

Page 15: Testing Spring MVC and REST Web Applications

15

Web Scopes – Review

request: lifecycle tied to the current HttpServletRequest

session: lifecycle tied to the current HttpSession

Page 16: Testing Spring MVC and REST Web Applications

16

Example: Request-scoped Bean Config

Page 17: Testing Spring MVC and REST Web Applications

17

Example: Request-scoped Bean Test

Page 18: Testing Spring MVC and REST Web Applications

18

Example: Session-scoped Bean Config

Page 19: Testing Spring MVC and REST Web Applications

19

Example: Session-scoped Bean Test

Page 20: Testing Spring MVC and REST Web Applications

20

ApplicationContextInitalizer

•  Introduced in Spring 3.1

•  Used for programmatic initialization of a ConfigurableApplicationContext

•  For example: –  to register property sources –  to activate profiles against the Environment

•  Configured in web.xml by specifying contextInitializerClasses via –  context-param for the ContextLoaderListener –  init-param for the DispatcherServlet

Page 21: Testing Spring MVC and REST Web Applications

21

Using Initializers in Tests

•  Configured in @ContextConfiguration via the initializers attribute

•  Inheritance can be controlled via the inheritInitializers attribute

•  An ApplicationContextInitializer may configure the entire context –  XML resource locations or annotated classes are no longer

required

•  Initializers are now part of the context cache key

•  Initializers are ordered based on Spring's Ordered interface or the @Order annotation

Page 22: Testing Spring MVC and REST Web Applications

22

Example: Multiple Initializers

Page 23: Testing Spring MVC and REST Web Applications

23

Application Context Hierarchies

•  Traditionally only flat, non-hierarchical contexts were supported in tests.

•  There was no easy way to create contexts with parent-child relationships.

•  But… hierarchies are supported in production.

•  Wouldn’t it be nice if you could test them, too?!

Page 24: Testing Spring MVC and REST Web Applications

24

Testing Context Hierarchies in 3.2.2

•  New @ContextHierarchy annotation –  Used in conjunction with @ContextConfiguration

•  @ContextConfiguration now supports a ‘name’ attribute –  for merging and overriding hierarchy configuration

Page 25: Testing Spring MVC and REST Web Applications

25

Single Test with Context Hierarchy

Page 26: Testing Spring MVC and REST Web Applications

26

Class and Context Hierarchies

Page 27: Testing Spring MVC and REST Web Applications

27

Testing Changes in 4.0

Gone: –  JUnit 3.8 support –  @ExpectedException –  @NotTransactional–  SimpleJdbcTestUtils

Updated: –  Servlet API mocks –  Spring MVC Test framework

Page 28: Testing Spring MVC and REST Web Applications

28

New Testing Features in 4.0

•  SocketUtils–  scan for UDP & TCP ports

•  ActiveProfilesResolver–  alternative to static profile strings –  set via new resolver attribute in @ActiveProfiles

•  Meta-annotation support for tests

Page 29: Testing Spring MVC and REST Web Applications

29

Meta-annotations in Tests

@ContextConfiguration({ "/app-config.xml", "/test-config.xml"})@ActiveProfiles("dev")@Transactional@Retention(RetentionPolicy.RUNTIME)public @interface TransactionalTest { }

@TransactionalTest@RunWith(SpringJUnit4ClassRunner.class)public class UserRepositoryIntegrationTests { /* ... */ }

Page 30: Testing Spring MVC and REST Web Applications

30

Spring MVC Test Framework

Page 31: Testing Spring MVC and REST Web Applications

31

What is Spring MVC Test?

•  Dedicated support for testing Spring MVC applications

•  Fluent API

•  Very easy to write

•  Includes client and server-side support

•  Servlet container not required

Page 32: Testing Spring MVC and REST Web Applications

32

Details

•  Included in spring-test module of Spring Framework 3.2 •  Builds on

–  TestContext framework for loading Spring MVC configuration

–  MockHttpServlet[Request|Response] and other mock types

•  Server-side tests involve DispatcherServlet

•  Client-side REST testing for code using RestTemplate

Page 33: Testing Spring MVC and REST Web Applications

33

Spring MVC Test History

•  Evolved as independent project on GitHub –  https://github.com/SpringSource/spring-test-mvc

•  Now folded into Spring Framework 3.2

•  Former project still supports Spring Framework 3.1

Page 34: Testing Spring MVC and REST Web Applications

34

Server-side Example

Page 35: Testing Spring MVC and REST Web Applications

35

A Note of Fluent API Usage

•  Requires static imports import static MockMvcRequestBuilders.get; import static MockMvcResultMatchers.status;

mockMvc.perform(get(“/foo”)) .andExpect(status().isOk())

•  Add as “favorite static members” in Eclipse preferences –  Java -> Editor -> Content Assist -> Favorites

Page 36: Testing Spring MVC and REST Web Applications

36

Server-side Test Recap

•  Actual Spring MVC configuration loaded

•  MockHttpServletRequest prepared

•  Executed via DispatcherServlet

•  Assertions applied on the resulting MockHttpServletResponse

Page 37: Testing Spring MVC and REST Web Applications

37

Integration or Unit Testing?

•  Mock request/response types, no Servlet container

•  However … –  DispatcherServlet + actual Spring MVC configuration

used

•  Hence … –  Not full end-to-end testing; does not replace Selenium –  However provides full confidence in Spring MVC web layer

•  In short, integration testing for Spring MVC –  Don't get too caught up in terminology!

Page 38: Testing Spring MVC and REST Web Applications

38

Strategy for Testing

•  Focus on testing the Spring MVC web layer alone –  Inject controllers with mock services or database

repositories

•  Thoroughly test Spring MVC –  Including code and configuration

•  Separate from lower layer integration tests –  e.g., data access tests

Page 39: Testing Spring MVC and REST Web Applications

39

Declaring a Mocked Dependency

•  Since we're loading actual Spring MVC config …

•  First declare mock dependency: <bean class="org.mockito.Mockito" factory-method="mock"> <constructor-arg value="org.example.FooRepository"/> </bean>

•  Then simply inject the mock instance into the test class –  Via @Autowired or @Inject –  Set up and reset via @Before, @Test, and @After methods

Page 40: Testing Spring MVC and REST Web Applications

40

What can be tested?

•  Response status, headers, and content –  Focus on asserting these first...

•  Spring MVC and Servlet specific results –  Model, flash, session, request attributes –  Mapped controller method and interceptors –  Resolved exceptions

•  Various options for asserting the response body –  JSONPath, XPath, XMLUnit –  Hamcrest matchers

Page 41: Testing Spring MVC and REST Web Applications

41

What about the view layer?

•  All view templating technologies will work –  Freemarker, Velocity, Thymeleaf, JSON, XML, PDF, etc.

•  Except for JSPs (no Servlet container!) –  But you can assert which JSP was selected

•  No redirecting and forwarding –  But you can assert the redirected or forwarded URL

•  Also of interest –  HTML Unit / Selenium Driver integration (experimental) –  https://github.com/SpringSource/spring-test-mvc-

htmlunit

Page 42: Testing Spring MVC and REST Web Applications

42

Useful Option for Debugging

Print all details to the console, i.e. System.out

mockMvc.perform("/foo")

.andDo(print()) .andExpect(status().isOk())

Page 43: Testing Spring MVC and REST Web Applications

43

“Standalone” Setup

•  No Spring configuration is loaded

•  Test one controller at a time

•  Just provide the controller instance

Page 44: Testing Spring MVC and REST Web Applications

44

“Standalone” Setup Example

Page 45: Testing Spring MVC and REST Web Applications

45

Test with Servlet Filters

Page 46: Testing Spring MVC and REST Web Applications

46

Re-use Request Props & Expectations

Page 47: Testing Spring MVC and REST Web Applications

47

Direct Access to underlying MvcResult

Page 48: Testing Spring MVC and REST Web Applications

48

Client-side REST Example

Page 49: Testing Spring MVC and REST Web Applications

49

Client-side REST Test Recap

•  An instance of RestTemplate configured with custom ClientHttpRequestFactory

•  Records and asserts expected requests –  Instead of executing them

•  Code using RestTemplate can now be invoked

•  Use verify() to assert all expectations were executed

Page 50: Testing Spring MVC and REST Web Applications

50

Acknowledgements

The Spring MVC Test support draws inspiration from a similar test framework in Spring Web Services.

Page 51: Testing Spring MVC and REST Web Applications

51

In Closing…

Page 52: Testing Spring MVC and REST Web Applications

52

Special Thanks to…

Rossen Stoyanchev

… for permitting reuse of his slides on Spring MVC Test!

Page 53: Testing Spring MVC and REST Web Applications

53

Spring Resources

•  Spring Framework –  http://projects.spring.io/spring-framework

•  Spring Forums –  http://forum.spring.io

•  Spring JIRA –  http://jira.springsource.org

•  Spring on GitHub –  https://github.com/spring-projects/spring-framework

Page 54: Testing Spring MVC and REST Web Applications

54

Spring MVC Test Resources

•  Blog post –  http://bit.ly/QCKMzh

•  Samples

–  https://github.com/spring-projects/spring-mvc-showcase –  http://bit.ly/VN1bPw … sample server tests –  http://bit.ly/13koRQP … sample client tests

•  Reference documentation –  http://bit.ly/SmUtD6

Page 55: Testing Spring MVC and REST Web Applications

55

Blogs

•  Swiftmind Team Blog –  http://www.swiftmind.com/blog

•  SpringSource Team Blog –  http://spring.io/blog

Page 56: Testing Spring MVC and REST Web Applications

56

Q & A

Sam Brannen @sam_brannen www.slideshare.net/sbrannen www.swiftmind.com