Spring Testing

Post on 10-May-2015

732 views 0 download

Tags:

description

Speaker: Mattias Severson Is it possible to decrease the turn-around time of your test suite? How can you make sure that your tests execute independently? Is it possible to automatically verify that the database schema is kept in sync with the source code? What are the trade-offs? In this presentation, you will learn how to apply features such as the Spring MVC Test Framework, Spring profiles, and embedded databases, to automate and improve your test suite, thus improving the overall quality of your project. A simplistic Spring web app will be used to show some practical code examples. Topics include: Basic Spring Testing Embedded Database Transactions Profiles Controller Tests Server Integration Tests

transcript

© 2013 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Spring TestingMattias Severson

Agenda

• Basic Spring Testing

• Embedded Database

• Transactions

• Profiles

• Controller Tests

• Server Integration Tests

2

3

Mattias

Bank App

4

AccountService

BankController

ImmutableAccount

AccountEntityAccountRepository

5

Architecture

Basics

6

jUnit Test

public class AccountServiceTest {

AccountService aService;

@Before public void setUp() { aService = new AccountServiceImpl(); }

@Test public void testDoSomething() { aService.doSomething(); // verify ... }}

7

public class AccountServiceTest {

@Autowired AccountService aService;

@Test public void testDoSomething() { aService.doSomething(); // verify ... }}

@Autowired

8

@ContextConfiguration("/application-context.xml")public class AccountServiceTest {

@Autowired AccountService aService;

@Test public void testDoSomething() { aService.doSomething(); // verify ... }}

public class AccountServiceTest {

@Autowired AccountService aService;

@Test public void testDoSomething() { aService.doSomething(); // verify ... }}

9

@ContextConfiguration

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("/application-context.xml")public class AccountServiceTest {

@Autowired AccountService aService;

@Test public void testDoSomething() { aService.doSomething(); // verify ... }}

@ContextConfiguration("/application-context.xml")public class AccountServiceTest {

@Autowired AccountService aService;

@Test public void testDoSomething() { aService.doSomething(); // verify ... }}

10

SpringJUnit4ClassRunner

• Caches ApplicationContext –static memory–unique context configuration–within the same test suite

• All tests execute in the same JVM

11

@ContextConfiguration

• @Before / @After–Mockito.reset(mockObject)–EasyMock.reset(mockObject)

• @DirtiesContext

12

Mocked Beans

Embedded DB

13

AccountRepository AccountEntity

XML Config

<jdbc:embedded-database id="dataSource" type="HSQL"> <jdbc:script location="classpath:db-schema.sql"/> <jdbc:script location="classpath:db-test-data.sql"/></jdbc:embedded-database>

14

Java Config

@Configurationpublic class EmbeddedDbConfig {

@Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.HSQL) .addScript(“classpath:db-schema.sql”) .addScript(“classpath:db-test-data.sql”) .build(); }}

15

Demo

16

Transactions

17

Tx Test

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("/application-context.xml")public class AccountServiceTest {

@Test public void testDoSomething() { // call DB }

}

@Transactional

@Test public void testDoSomething() { // call DB }

18

Tx Annotations

• @TransactionConfiguration

• @BeforeTransaction

• @AfterTransaction

• @Rollback

19

Avoid False Positives

• Always flush() before validation!

–JPA • entityManager.flush();

–Hibernate• sessionFactory.getCurrentSession().flush();

20

Demo

21

No Transactions?

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("...")public class AccountRepositoryTest {

@Autowired AccountRepository accountRepo;

@Before public void setUp() { accountRepo.deleteAll(); accountRepo.save(testData); }}

22

Spring Profiles

23

XML Profiles

<beans ...>

<bean id="dataSource"> <!-- Test data source --> </bean>

<bean id="dataSource"> <!-- Production data source --> </bean>

</beans>

<beans profile="testProfile">

</beans>

<beans profile="prodProfile">

</beans>

24

Java Config Profile

@Configurationpublic class EmbeddedDbConfig {

@Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder(). // ... }}

@Profile(“testProfile”)

25

Component Profile

@Componentpublic class SomeClass implements SomeInterface {

}

@Profile(“testProfile”)

26

Tests and Profiles

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(“/application-context.xml”)public class SomeTest {

@Autowired SomeClass someClass;

@Test public void testSomething() { ... }}

@ActiveProfiles("testProfile")

27

Demo

28

AccountRepository AccountEntity

AccountService ImmutableAccount

web.xml

<web-app ...>

<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>

</web-app>

<context-param> <param-name>spring.profiles.active</param-name> <param-value>someProfile</param-value> </context-param>

29

ApplicationContext

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();ctx.getEnvironment().setActiveProfiles("someProfile");ctx.register(SomeConfig.class);ctx.scan("com.jayway.demo");ctx.refresh();

30

Env Property

System.getProperty(“spring.profiles.active”);

mvn -Dspring.profiles.active=testProfile

31

Default Profiles

ctx.getEnvironment().setDefaultProfiles("...");

System.getProperty("spring.profiles.default");

32

<context-param> <param-name>spring.profiles.default</param-name> <param-value>defaultProfile</param-value></context-param>

<beans profile="default"> <!-- default beans --></beans>

@Profile("default")

Profile Alternatives

33

• .properties

• Maven Profile

Test Controller AccountRepository

AccountService

AccountEntity

ImmutableAccount

BankController

34

Spring MVC Test Framework

• Call Controllers through DispatcherServlet

• MockHttpServletRequest• MockHttpServletResponse

35

MockMvc

MockMvc mockMvc = MockMvcBuilders .standaloneSetup(new BankController()) .build();

36

MockMvc mockMvc = MockMvcBuilders .standaloneSetup(new BankController()) .setMessageConverters(...) .setValidator(...) .setConversionService(...) .addInterceptors(...) .setViewResolvers(...) .setLocaleResolver(...) .addFilter(...) .build();

Assertions

mockMvc.perform(get("/url") .accept(MediaType.APPLICATION_XML)) .andExpect(response().status().isOk()) .andExpect(content().contentType(“MediaType.APPLICATION_XML”)) .andExpect(xpath(“key”).string(“value”)) .andExpect(redirectedUrl(“url”)) .andExpect(model().attribute(“name”, value));

37

@WebAppConfiguration

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("/application-context.xml")@WebAppConfigurationpublic class WebApplicationTest {

@Autowired WebApplicationContext wac;

MockMvc mockMvc;

@Before public void setup() { mockMvc = MockMvcBuilders .webAppContextSetup(wac) .build(); }

38

Demo

39

Testing Views

• Supported templates–JSON–XML–Velocity–Thymeleaf

• Except JSP

40

Server Integration Tests

41

appCtx

Spring Integration Test

42

Embedded DB

txMngr

test

dataSrc

App Server

appCtx

Server Integration Test

43

Embedded DB

txMngr

test

dataSrc

HTTP

App Server

App Server

44

appCtx

DB

txMngrdataSrc

testAppCtx

dataSrc

testHTTP

jetty-maven-plugin<executions> <execution> <id>start-jetty</id> <phase>pre-integration-test</phase> <goals> <goal>run</goal> </goals> </execution> <execution> <id>stop-jetty</id> <phase>post-integration-test</phase> <goals> <goal>stop</goal> </goals> </execution></executions>

45

maven-failsafe-plugin

**/IT*.java**/*IT.java**/*ITCase.java

46

Test RESTful API

47

• RestTemplate• Selenium• HttpClient• ...

REST Assured

@Test public void shouldGetSingleAccount() { expect(). statusCode(HttpStatus.SC_OK). contentType(ContentType.JSON). body("accountNumber", is(1)). body("balance", is(100)). when(). get("/account/1"); }

48

Demo

49

Questions?

50

Learn More. Stay Connected.

Talk to us on Twitter: @springcentralFind session replays on YouTube: spring.io/video

@mattiasseverson

http://blog.jayway.com/author/mattiasseverson/