SPRINGONE2GX
WASHINGTON, DC
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons Attribution -NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Get the Most out of Testing
with Spring 4.2
Sam Brannen
@sam_brannen
Nicolas Fränkel
@nicolas_frankel
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Sam Brannen
• Spring and Enterprise Java Consultant @ Swiftmind
• Java Developer for over 17 years
• Spring Framework Core Committer since 2007
• Component lead for spring-test
• Creator of @AliasFor
• Spring Trainer
• Speaker on Spring, Java, and testing
• Swiss Spring User Group Lead
2
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ 3
Your experts for Spring and Enterprise Java
Areas of expertise
• Spring *
• Java EE
• Software Architecture
• Software Engineering Best
Practices
Where you find us
• Zurich, Switzerland
• @swiftmind
• http://www.swiftmind.com
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Nicolas Fränkel
• Developer & Architect
• Consultant
• Teacher & Trainer
• Blogger
• Book Author
4
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Learning Vaadin 7
Integration Testing from the
Trenches
5
Nicolas’ Books
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Agenda
• Spring Events App
• New in Spring 4.2
• JUnit vs. TestNG
• Spring Boot Tests
• Spring Security Tests
• Tips & Tricks
6
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Show of hands…
7
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Spring Events App
8
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
The Spring Events Example Application
• Spring Boot powered web app
• Simple POJO domain model: Event
• Transactional service layer
• Spring Data JPA repository layer
• Spring @MVC +Thymeleaf & REST presentation layer
• Spring Security
• https://github.com/sbrannen/spring-events
9
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
New in Spring Framework 4.2
10
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
@AliasFor
• New in Spring Framework 4.2, refined in 4.2.1 
• Used to declare aliases between attributes within an annotation
• e.g., locations and value in @ContextConfiguration, or
path and value in @RequestMapping
• Used in composed annotations to declare explicit overrides of attributes in
meta-annotations
• e.g., @Get, @Post, @GetJson, @TransactionalService
• See Spring Composed project for examples
• https://github.com/sbrannen/spring-composed
11
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Composable Annotations w/ Overrides: pre 4.2
• Composable annotations can override attributes of meta-annotations
• Purely convention-based
• Matched by attribute name and type
• Can lead to potential naming conflicts
• Cannot override the value attribute
12
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Convention-based Attribute Override
@Target(TYPE)
@Retention(RUNTIME)
@ContextConfiguration
@Transactional
public @interface TransactionalTest {
String[] locations() default {};
}
@TransactionalTest(locations = "/order-test-config.xml")
public class OrderRepositoryTests { }
13
seen as locations in
@ContextConfiguration
redeclares locations attribute
declares locations attribute
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Conflict w/ Convention-based Attribute
Override
@Target(TYPE)
@Retention(RUNTIME)
@ContextConfiguration
@TestPropertySource
@Transactional
public @interface TransactionalTest {
String[] locations() default {};
}
@TransactionalTest(locations = "/order-test-config.xml")
public class OrderRepositoryTests { }
14
both declare locations attribute
ambiguous
which one?!
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Composable Annotations w/ Overrides: post
4.2
• Composable annotations can explicitly override attributes of meta-annotations,
even transitively
• Attributes within an annotation that effectively override the same attribute are
treated as implicit aliases for each other
• Explicitly declared via @AliasFor
• Can avoid potential naming conflicts
• Can even override the value attribute
15
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Avoid Attribute Override Conflict w/ @AliasFor
(1)
@ContextConfiguration
@TestPropertySource
@Transactional
public @interface TransactionalTest {
@AliasFor(annotation = ContextConfiguration.class,
attribute = "locations")
String[] xmlFiles() default {};
@AliasFor(annotation = TestPropertySource.class,
attribute = "locations")
String[] propFiles() default {};
}
16
both declare locations attribute
explicit
explicit
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Avoid Attribute Override Conflict w/ @AliasFor
(2)
@TransactionalTest(
xmlFiles = "/order-test-config.xml",
propFiles = "/order-test.properties"
)
public class OrderRepositoryTests {
}
17
seen as locations in
@ContextConfiguration
seen as locations in
@TestPropertySource
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Embedded Databases – What’s in a Name?
Q: Why should I care what my embedded database is named?
A: Because you’ll run into problems if your DataSource config is imported from
multiple places within your test suite.
Q: Why? Doesn’t it just create a new instance of the database?
A: Recreating an embedded database within the same JVM doesn’t actually create
anything: a second attempt simply connects to the existing one.
Q: Ummmm… What?!
A: When you connect to an embedded database, it gets created if it doesn’t already
exist; otherwise, you just connect to the existing instance. Assigning each one a
unique name results in different JDBC connection URLs and thus different
instances.
18
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Unique Names for Embedded Databases
19
• EmbeddedDatabaseBuilder
• setName() – since 3.0
• generateUniqueName() – since 4.2
• <jdbc:embedded-database>
• id – used as name since 3.0
o but bad since the id is usually “dataSource”... i.e., not unique
• database-name – since 4.2
• generate-name – since 4.2
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Ex: Embedded Database in Java Config
20
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.addScript("schema.sql")
.addScript("user_data.sql")
.build();
}
New in Spring 4.2
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Ex: Embedded Database XML Config
21
<jdbc:embedded-database id="dataSource" generate-name="true">
<jdbc:script location="classpath:/schema.sql" />
<jdbc:script location="classpath:/user_data.sql" />
</jdbc:embedded-database>
New in Spring 4.2
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Spring Cleaning
• @TransactionConfiguration
• Deprecated in 4.2
• @Rollback (and @Commit) now supported at the class level
• Use @Transactional qualifiers
• AssertThrows
• Deprecated in 3.x; gone in 4.2
• JUnit: use @Test(expected = ...) or @Rule ExpectedException
• TestNG: use @Test(expectedExceptions = ...)
22
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Extension Points
• ContextCache
• Now a public API with DefaultContextCache implementation
• DefaultTestContext, DefaultBootstrapContext, and
DefaultCacheAwareContextLoaderDelegate
• Now public classes, allowing for custom extensions
• TestContextBootstrapper
• Now responsible for building the TestContext
23
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Spring + JUnit … @Rules!
• SpringJUnit4ClassRunner
• Serving the community since Spring 2.5 (2007)
• But… can’t be used with other runners
o JUnit's Parameterized, MockitoJUnitRunner, etc.
• SpringClassRule & SpringMethodRule
• Since Spring 4.2
• Can be used with any JUnit runner!
• Have to be used together
• Provide full power of the Spring TestContext Framework
24
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Ex: SpringClassRule & SpringMethodRule
25
@RunWith(Parameterized.class)
@ContextConfiguration
public class ParameterizedSpringRuleTests {
@ClassRule
public static final SpringClassRule SPRING_CLASS_RULE
= new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule
= new SpringMethodRule();
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
HtmlUnit, Selenium, & Geb
• First-class support for HtmlUnit and Selenium in Spring MVC Test
• Initially a stand-alone project
• Incorporated into spring-test in Spring 4.2
• Page-based web app testing w/o a Servlet container
• The Selenium support can also be used with Geb
26
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
MockMvc & HtmlUnit WebClient Setup
• spring-test (4.2+) & htmlunit (2.18+)
• MockMvcWebClientBuilder: several options, simplest case below
27
@Autowired WebApplicationContext wac;
WebClient webClient;
@Before
public void setup() {
webClient = MockMvcWebClientBuilder
.webAppContextSetup(wac).build();
}
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
MockMvc & Selenium WebDriver Setup
• spring-test (4.2+) & selenium-htmlunit-driver (2.47+)
• MockMvcHtmlUnitDriverBuilder: several options, simplest case below
28
@Autowired WebApplicationContext wac;
WebDriver webDriver;
@Before
public void setup() {
webDriver = MockMvcHtmlUnitDriverBuilder
.webAppContextSetup(wac).build();
}
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Odds & Ends (1)
• ReflectionTestUtils
• Now you can get or set static fields, including constants
• AopTestUtils
• Obtain reference to target object hidden behind one or more Spring proxies
• Useful if your mock gets proxied (e.g., if your interface is @Transactional)
• @DirtiesContext
• New BEFORE_METHOD, BEFORE_CLASS, &
BEFORE_EACH_TEST_METHOD modes
• Requires DirtiesContextBeforeModesTestExecutionListener, enabled by
default
29
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
ReflectionTestUtils vs. Proper Design
• Proper design mandates that we use the most narrow visibility possible.
• But it’s sometimes meaningful to test private methods, or change values of
final fields, etc.
• As a work-around, set the visibility to package (no keyword) and put the test
class in the same package.
• Guava provides the @VisibleForTesting annotation to document this hack.
• ReflectionTestUtils is an alternative to such work-arounds that promotes proper
design.
30
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Odds & Ends (2)
• @Commit
• Syntactical sugar for @Rollback(false)
• Inlined statements with @Sql
• When a dedicated SQL script is overkill
• Configured via the new statements attribute
• Executed after SQL scripts in same @Sql annotation
• Great for one-liners
• Spring MVC Test - MvcResult logging
• New log(), print(OutputStream), and print(Writer) methods in
MockMvcResultHandlers complement existing print() method
31
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ 32
@Test
@Sql(statements = "DROP TABLE user IF EXISTS")
@Sql(
scripts = "/test-schema.sql",
statements = "INSERT INTO user VALUES ('Dilbert')"
)
public void userTest() {
// code that uses the test schema and test user
}
Ex: Inlined @Sql Statements
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ 33
@Before
public void setUpMockMvc() {
mockMvc = MockMvcBuilders
.webAppContextSetup(wac)
.alwaysDo(print(System.err))
.build();
}
Ex: Logging MvcResult to STDERR
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
JUnit vs TestNG
34
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
JUnit
• De facto testing framework for Java
• Most popular library in the entire
Java ecosystem
• http://bit.ly/1iwwboO
35
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
JUnit
• Unit for… unit testing!
• Test methods are independent and isolated
• Simplicity can be both a pro and a con
• Can be used for integration testing, too
• Test methods are unordered
• Unless you use @FixMethodOrder
• Single Runner
• Spring OR Mockito OR Parameterized
• Rules to the rescue
36
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
TestNG
• Implemented test annotations before JUnit
• Richer lifecycle than JUnit
• Ordering and grouping of test methods
• Concurrent test execution
37
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Spring Boot Tests
38
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Integration Tests with Spring Boot
• @SpringApplicationConfiguration
• Like @ContextConfiguration but with SpringApplicationContextLoader
• Fully Loaded
• @IntegrationTest
o IntegrationTestPropertiesListener vs. @TestPropertySource
• @WebIntegrationTest
• Limit scope of auto-configuration
• @TestRepositoryConfig as example
39
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Spring Security Tests
40
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Spring Security Test Annotations
• WithSecurityContextTestExecutionListener
• auto-detected
• @WithMockUser
• See RestEventsControllerIT in spring-events
• @WithUserDetails
• @WithSecurityContext
41
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Spring Security & MockMvc
• apply(springSecurity())
• with(...)
• user(...)
• authentication(...)
• securityContext(...)
• httpBasic(...)
• perform(...)
• formLogin()
• logout()
42
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Testing Tips & Tricks
43
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Eclipse
• Define key bindings for executing tests quickly
• Alt + Shift + X… T  too awkward to type frequently!
• Sam’s personal settings:
o Run JUnit Test  Ctrl + J
o Rerun JUnit Test  Ctrl + Shift + J
• Set up content assist favorites for common static imports
• org.junit.Assert OR org.assertj.core.api.Assertions
• org.mockito.Mockito
• org.springframework.test.web.servlet.request.MockMvcRequestBuilders
• org.springframework.test.web.servlet.result.MockMvcResultMatchers
44
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Context Caching
• Granularity of context configuration files
• Goal: one entry point for production and one for testing
• But… not very practical: you’ll need to support different scenarios
• Too many constellations  too many contexts
• Too few constellations  all tests use the same config
• Optimum use of the context cache
• Avoid frequent use of @DirtiesContext
• Cache statistics are logged at DEBUG level for category
org.springframework.test.context.cache
45
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Integration Tests: Spring Boot vs. Spring Core
• The key differences are speed and scope
• @SpringApplicationConfiguration vs. @ContextConfiguration
• @EnableAutoConfiguration vs. hand-crafted test @Configuration
• See @TestRepositoryConfig in spring-events app
46
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Scope
• Think about the scope of your test
• SUT: Subject Under Test
• The larger the SUT, the smaller the
number of tests
• Mock or fake the dependencies of
your SUT
47
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
End-to-end Testing
• A few nominal scenarios
• Very brittle
• Use the Page pattern
• Decouples the page structure from the test itself
48
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Integration Testing Challenges
• Speed
• Diagnosing the problem
• Brittleness
49
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Speed
• Integration tests are often slow
• Execute unit tests before integration tests
• No need to run integration tests if unit tests fail
• Separate unit and integration tests in the build
• Maven: use the maven-failsafe-plugin
• Gradle: configure dependent Test tasks
o See spring-events for an example
50
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Diagnosing the Problem
• Consider an e-commerce checkout process
• Multi-step use case
• Many places where things can go wrong
• Use small, focused, and aptly named methods
• Order and group methods
• According to the steps in the process
• Easy with TestNG; possible with JUnit
51
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Brittleness
• All applications have infrastructure dependencies
• Database, web services, file system, time, etc.
• External dependencies might be unavailable during testing
• Sends a bad signal to developers
• Causes builds to fail intermittently
• Solution: approximate the production environment
• Mock or fake external dependencies
52
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Developer & Test Databases
• Embedded databases
• HSQL, H2, Derby
• in-memory or persistent mode
• H2 supports compatibility modes for Oracle, MySQL, etc.
• Developer databases
• Use a single schema per developer if possible
• Be aware of the mismatch if you’re not using the same RDBMS in tests as in
production
53
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Fake Remote Web Services with SoapUI &
Spark
• SOAP
• SoapUI has an API
• REST
• Spark
54
setPort(5678);
get("/hello", (request, response) -> {
return "Hello World!";
});
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Mock Remote Web Services with Spring
• In-memory mocks for remote Web Service endpoints
• Don’t actually connect to a server over the network
• SOAP – Spring Web Services
• spring-ws-test module
• MockWebServiceServer
• REST – Spring MVC REST
• spring-test module
• MockRestServiceServer
55
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
DataSource pool exhaustion check
• Set the maximum number of connections in the pool to 1
• Tests blow up fast if connections are not returned to pool
56
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Checking the database when a test fails
If a database related test is failing…
• Commit your transactions in your tests
• Via @Commit or the TestTransaction API
• Use a clean setup strategy
• Instead of a clean tear down strategy
• Use a file based database
• Use persistent storage mode for embedded DBs
• Inspect database state after failed test
57
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Testing is about Saving Money
• Not about having more test coverage than your neighbor
• Think about ROI
58
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
JUnit Lambda
59
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Give back to the project that’s given us so
much!
• JUnit is the de facto standard testing
framework in the Java ecosystem
• Last major release 10 years ago
• Times have changed: Java 8, etc.
• Introducing … JUnit Lambda … the
crowdfunding campaign to help make the
next major release of JUnit a reality
• Pitch in if you can, & help spread the word!
• @JUnitLambda
• https://www.indiegogo.com/projects/junit-lambda
60
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
In closing…
61
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Spring Resources
Spring Framework
http://projects.spring.io/spring-framework
Spring Guides
http://spring.io/guides
Spring JIRA
https://jira.spring.io
Spring on GitHub
https://github.com/spring-projects/spring-framework
Stack Overflow
spring, spring-test, spring-mvc, spring-boot, spring-security, …
62
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/
Blogs
Spring Blog
http://spring.io/blog
Swiftmind Blog
http://www.swiftmind.com/blog
Nicolas Fränkel’s Blog
https://blog.frankel.ch
63
© 2013-2015 Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons
Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ 64
Sam Brannen
@sam_brannen
www.slideshare.net/sbrannen
www.swiftmind.com
Learn More. Stay Connected.
@springcentral Spring.io/video Nicolas Fränkel
@nicolas_frankel

Get the Most out of Testing with Spring 4.2

  • 1.
    SPRINGONE2GX WASHINGTON, DC © 2013-2015Sam Brannen & Nicolas Fränkel and licensed under a Creative Commons Attribution -NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Get the Most out of Testing with Spring 4.2 Sam Brannen @sam_brannen Nicolas Fränkel @nicolas_frankel
  • 2.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Sam Brannen • Spring and Enterprise Java Consultant @ Swiftmind • Java Developer for over 17 years • Spring Framework Core Committer since 2007 • Component lead for spring-test • Creator of @AliasFor • Spring Trainer • Speaker on Spring, Java, and testing • Swiss Spring User Group Lead 2
  • 3.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ 3 Your experts for Spring and Enterprise Java Areas of expertise • Spring * • Java EE • Software Architecture • Software Engineering Best Practices Where you find us • Zurich, Switzerland • @swiftmind • http://www.swiftmind.com
  • 4.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Nicolas Fränkel • Developer & Architect • Consultant • Teacher & Trainer • Blogger • Book Author 4
  • 5.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Learning Vaadin 7 Integration Testing from the Trenches 5 Nicolas’ Books
  • 6.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Agenda • Spring Events App • New in Spring 4.2 • JUnit vs. TestNG • Spring Boot Tests • Spring Security Tests • Tips & Tricks 6
  • 7.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Show of hands… 7
  • 8.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Spring Events App 8
  • 9.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ The Spring Events Example Application • Spring Boot powered web app • Simple POJO domain model: Event • Transactional service layer • Spring Data JPA repository layer • Spring @MVC +Thymeleaf & REST presentation layer • Spring Security • https://github.com/sbrannen/spring-events 9
  • 10.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ New in Spring Framework 4.2 10
  • 11.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ @AliasFor • New in Spring Framework 4.2, refined in 4.2.1  • Used to declare aliases between attributes within an annotation • e.g., locations and value in @ContextConfiguration, or path and value in @RequestMapping • Used in composed annotations to declare explicit overrides of attributes in meta-annotations • e.g., @Get, @Post, @GetJson, @TransactionalService • See Spring Composed project for examples • https://github.com/sbrannen/spring-composed 11
  • 12.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Composable Annotations w/ Overrides: pre 4.2 • Composable annotations can override attributes of meta-annotations • Purely convention-based • Matched by attribute name and type • Can lead to potential naming conflicts • Cannot override the value attribute 12
  • 13.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Convention-based Attribute Override @Target(TYPE) @Retention(RUNTIME) @ContextConfiguration @Transactional public @interface TransactionalTest { String[] locations() default {}; } @TransactionalTest(locations = "/order-test-config.xml") public class OrderRepositoryTests { } 13 seen as locations in @ContextConfiguration redeclares locations attribute declares locations attribute
  • 14.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Conflict w/ Convention-based Attribute Override @Target(TYPE) @Retention(RUNTIME) @ContextConfiguration @TestPropertySource @Transactional public @interface TransactionalTest { String[] locations() default {}; } @TransactionalTest(locations = "/order-test-config.xml") public class OrderRepositoryTests { } 14 both declare locations attribute ambiguous which one?!
  • 15.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Composable Annotations w/ Overrides: post 4.2 • Composable annotations can explicitly override attributes of meta-annotations, even transitively • Attributes within an annotation that effectively override the same attribute are treated as implicit aliases for each other • Explicitly declared via @AliasFor • Can avoid potential naming conflicts • Can even override the value attribute 15
  • 16.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Avoid Attribute Override Conflict w/ @AliasFor (1) @ContextConfiguration @TestPropertySource @Transactional public @interface TransactionalTest { @AliasFor(annotation = ContextConfiguration.class, attribute = "locations") String[] xmlFiles() default {}; @AliasFor(annotation = TestPropertySource.class, attribute = "locations") String[] propFiles() default {}; } 16 both declare locations attribute explicit explicit
  • 17.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Avoid Attribute Override Conflict w/ @AliasFor (2) @TransactionalTest( xmlFiles = "/order-test-config.xml", propFiles = "/order-test.properties" ) public class OrderRepositoryTests { } 17 seen as locations in @ContextConfiguration seen as locations in @TestPropertySource
  • 18.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Embedded Databases – What’s in a Name? Q: Why should I care what my embedded database is named? A: Because you’ll run into problems if your DataSource config is imported from multiple places within your test suite. Q: Why? Doesn’t it just create a new instance of the database? A: Recreating an embedded database within the same JVM doesn’t actually create anything: a second attempt simply connects to the existing one. Q: Ummmm… What?! A: When you connect to an embedded database, it gets created if it doesn’t already exist; otherwise, you just connect to the existing instance. Assigning each one a unique name results in different JDBC connection URLs and thus different instances. 18
  • 19.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Unique Names for Embedded Databases 19 • EmbeddedDatabaseBuilder • setName() – since 3.0 • generateUniqueName() – since 4.2 • <jdbc:embedded-database> • id – used as name since 3.0 o but bad since the id is usually “dataSource”... i.e., not unique • database-name – since 4.2 • generate-name – since 4.2
  • 20.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Ex: Embedded Database in Java Config 20 @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .generateUniqueName(true) .addScript("schema.sql") .addScript("user_data.sql") .build(); } New in Spring 4.2
  • 21.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Ex: Embedded Database XML Config 21 <jdbc:embedded-database id="dataSource" generate-name="true"> <jdbc:script location="classpath:/schema.sql" /> <jdbc:script location="classpath:/user_data.sql" /> </jdbc:embedded-database> New in Spring 4.2
  • 22.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Spring Cleaning • @TransactionConfiguration • Deprecated in 4.2 • @Rollback (and @Commit) now supported at the class level • Use @Transactional qualifiers • AssertThrows • Deprecated in 3.x; gone in 4.2 • JUnit: use @Test(expected = ...) or @Rule ExpectedException • TestNG: use @Test(expectedExceptions = ...) 22
  • 23.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Extension Points • ContextCache • Now a public API with DefaultContextCache implementation • DefaultTestContext, DefaultBootstrapContext, and DefaultCacheAwareContextLoaderDelegate • Now public classes, allowing for custom extensions • TestContextBootstrapper • Now responsible for building the TestContext 23
  • 24.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Spring + JUnit … @Rules! • SpringJUnit4ClassRunner • Serving the community since Spring 2.5 (2007) • But… can’t be used with other runners o JUnit's Parameterized, MockitoJUnitRunner, etc. • SpringClassRule & SpringMethodRule • Since Spring 4.2 • Can be used with any JUnit runner! • Have to be used together • Provide full power of the Spring TestContext Framework 24
  • 25.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Ex: SpringClassRule & SpringMethodRule 25 @RunWith(Parameterized.class) @ContextConfiguration public class ParameterizedSpringRuleTests { @ClassRule public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule(); @Rule public final SpringMethodRule springMethodRule = new SpringMethodRule();
  • 26.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ HtmlUnit, Selenium, & Geb • First-class support for HtmlUnit and Selenium in Spring MVC Test • Initially a stand-alone project • Incorporated into spring-test in Spring 4.2 • Page-based web app testing w/o a Servlet container • The Selenium support can also be used with Geb 26
  • 27.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ MockMvc & HtmlUnit WebClient Setup • spring-test (4.2+) & htmlunit (2.18+) • MockMvcWebClientBuilder: several options, simplest case below 27 @Autowired WebApplicationContext wac; WebClient webClient; @Before public void setup() { webClient = MockMvcWebClientBuilder .webAppContextSetup(wac).build(); }
  • 28.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ MockMvc & Selenium WebDriver Setup • spring-test (4.2+) & selenium-htmlunit-driver (2.47+) • MockMvcHtmlUnitDriverBuilder: several options, simplest case below 28 @Autowired WebApplicationContext wac; WebDriver webDriver; @Before public void setup() { webDriver = MockMvcHtmlUnitDriverBuilder .webAppContextSetup(wac).build(); }
  • 29.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Odds & Ends (1) • ReflectionTestUtils • Now you can get or set static fields, including constants • AopTestUtils • Obtain reference to target object hidden behind one or more Spring proxies • Useful if your mock gets proxied (e.g., if your interface is @Transactional) • @DirtiesContext • New BEFORE_METHOD, BEFORE_CLASS, & BEFORE_EACH_TEST_METHOD modes • Requires DirtiesContextBeforeModesTestExecutionListener, enabled by default 29
  • 30.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ ReflectionTestUtils vs. Proper Design • Proper design mandates that we use the most narrow visibility possible. • But it’s sometimes meaningful to test private methods, or change values of final fields, etc. • As a work-around, set the visibility to package (no keyword) and put the test class in the same package. • Guava provides the @VisibleForTesting annotation to document this hack. • ReflectionTestUtils is an alternative to such work-arounds that promotes proper design. 30
  • 31.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Odds & Ends (2) • @Commit • Syntactical sugar for @Rollback(false) • Inlined statements with @Sql • When a dedicated SQL script is overkill • Configured via the new statements attribute • Executed after SQL scripts in same @Sql annotation • Great for one-liners • Spring MVC Test - MvcResult logging • New log(), print(OutputStream), and print(Writer) methods in MockMvcResultHandlers complement existing print() method 31
  • 32.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ 32 @Test @Sql(statements = "DROP TABLE user IF EXISTS") @Sql( scripts = "/test-schema.sql", statements = "INSERT INTO user VALUES ('Dilbert')" ) public void userTest() { // code that uses the test schema and test user } Ex: Inlined @Sql Statements
  • 33.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ 33 @Before public void setUpMockMvc() { mockMvc = MockMvcBuilders .webAppContextSetup(wac) .alwaysDo(print(System.err)) .build(); } Ex: Logging MvcResult to STDERR
  • 34.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ JUnit vs TestNG 34
  • 35.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ JUnit • De facto testing framework for Java • Most popular library in the entire Java ecosystem • http://bit.ly/1iwwboO 35
  • 36.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ JUnit • Unit for… unit testing! • Test methods are independent and isolated • Simplicity can be both a pro and a con • Can be used for integration testing, too • Test methods are unordered • Unless you use @FixMethodOrder • Single Runner • Spring OR Mockito OR Parameterized • Rules to the rescue 36
  • 37.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ TestNG • Implemented test annotations before JUnit • Richer lifecycle than JUnit • Ordering and grouping of test methods • Concurrent test execution 37
  • 38.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Spring Boot Tests 38
  • 39.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Integration Tests with Spring Boot • @SpringApplicationConfiguration • Like @ContextConfiguration but with SpringApplicationContextLoader • Fully Loaded • @IntegrationTest o IntegrationTestPropertiesListener vs. @TestPropertySource • @WebIntegrationTest • Limit scope of auto-configuration • @TestRepositoryConfig as example 39
  • 40.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Spring Security Tests 40
  • 41.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Spring Security Test Annotations • WithSecurityContextTestExecutionListener • auto-detected • @WithMockUser • See RestEventsControllerIT in spring-events • @WithUserDetails • @WithSecurityContext 41
  • 42.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Spring Security & MockMvc • apply(springSecurity()) • with(...) • user(...) • authentication(...) • securityContext(...) • httpBasic(...) • perform(...) • formLogin() • logout() 42
  • 43.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Testing Tips & Tricks 43
  • 44.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Eclipse • Define key bindings for executing tests quickly • Alt + Shift + X… T  too awkward to type frequently! • Sam’s personal settings: o Run JUnit Test  Ctrl + J o Rerun JUnit Test  Ctrl + Shift + J • Set up content assist favorites for common static imports • org.junit.Assert OR org.assertj.core.api.Assertions • org.mockito.Mockito • org.springframework.test.web.servlet.request.MockMvcRequestBuilders • org.springframework.test.web.servlet.result.MockMvcResultMatchers 44
  • 45.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Context Caching • Granularity of context configuration files • Goal: one entry point for production and one for testing • But… not very practical: you’ll need to support different scenarios • Too many constellations  too many contexts • Too few constellations  all tests use the same config • Optimum use of the context cache • Avoid frequent use of @DirtiesContext • Cache statistics are logged at DEBUG level for category org.springframework.test.context.cache 45
  • 46.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Integration Tests: Spring Boot vs. Spring Core • The key differences are speed and scope • @SpringApplicationConfiguration vs. @ContextConfiguration • @EnableAutoConfiguration vs. hand-crafted test @Configuration • See @TestRepositoryConfig in spring-events app 46
  • 47.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Scope • Think about the scope of your test • SUT: Subject Under Test • The larger the SUT, the smaller the number of tests • Mock or fake the dependencies of your SUT 47
  • 48.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ End-to-end Testing • A few nominal scenarios • Very brittle • Use the Page pattern • Decouples the page structure from the test itself 48
  • 49.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Integration Testing Challenges • Speed • Diagnosing the problem • Brittleness 49
  • 50.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Speed • Integration tests are often slow • Execute unit tests before integration tests • No need to run integration tests if unit tests fail • Separate unit and integration tests in the build • Maven: use the maven-failsafe-plugin • Gradle: configure dependent Test tasks o See spring-events for an example 50
  • 51.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Diagnosing the Problem • Consider an e-commerce checkout process • Multi-step use case • Many places where things can go wrong • Use small, focused, and aptly named methods • Order and group methods • According to the steps in the process • Easy with TestNG; possible with JUnit 51
  • 52.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Brittleness • All applications have infrastructure dependencies • Database, web services, file system, time, etc. • External dependencies might be unavailable during testing • Sends a bad signal to developers • Causes builds to fail intermittently • Solution: approximate the production environment • Mock or fake external dependencies 52
  • 53.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Developer & Test Databases • Embedded databases • HSQL, H2, Derby • in-memory or persistent mode • H2 supports compatibility modes for Oracle, MySQL, etc. • Developer databases • Use a single schema per developer if possible • Be aware of the mismatch if you’re not using the same RDBMS in tests as in production 53
  • 54.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Fake Remote Web Services with SoapUI & Spark • SOAP • SoapUI has an API • REST • Spark 54 setPort(5678); get("/hello", (request, response) -> { return "Hello World!"; });
  • 55.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Mock Remote Web Services with Spring • In-memory mocks for remote Web Service endpoints • Don’t actually connect to a server over the network • SOAP – Spring Web Services • spring-ws-test module • MockWebServiceServer • REST – Spring MVC REST • spring-test module • MockRestServiceServer 55
  • 56.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ DataSource pool exhaustion check • Set the maximum number of connections in the pool to 1 • Tests blow up fast if connections are not returned to pool 56
  • 57.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Checking the database when a test fails If a database related test is failing… • Commit your transactions in your tests • Via @Commit or the TestTransaction API • Use a clean setup strategy • Instead of a clean tear down strategy • Use a file based database • Use persistent storage mode for embedded DBs • Inspect database state after failed test 57
  • 58.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Testing is about Saving Money • Not about having more test coverage than your neighbor • Think about ROI 58
  • 59.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ JUnit Lambda 59
  • 60.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Give back to the project that’s given us so much! • JUnit is the de facto standard testing framework in the Java ecosystem • Last major release 10 years ago • Times have changed: Java 8, etc. • Introducing … JUnit Lambda … the crowdfunding campaign to help make the next major release of JUnit a reality • Pitch in if you can, & help spread the word! • @JUnitLambda • https://www.indiegogo.com/projects/junit-lambda 60
  • 61.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ In closing… 61
  • 62.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Spring Resources Spring Framework http://projects.spring.io/spring-framework Spring Guides http://spring.io/guides Spring JIRA https://jira.spring.io Spring on GitHub https://github.com/spring-projects/spring-framework Stack Overflow spring, spring-test, spring-mvc, spring-boot, spring-security, … 62
  • 63.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ Blogs Spring Blog http://spring.io/blog Swiftmind Blog http://www.swiftmind.com/blog Nicolas Fränkel’s Blog https://blog.frankel.ch 63
  • 64.
    © 2013-2015 SamBrannen & Nicolas Fränkel and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by -nc/3.0/ 64 Sam Brannen @sam_brannen www.slideshare.net/sbrannen www.swiftmind.com Learn More. Stay Connected. @springcentral Spring.io/video Nicolas Fränkel @nicolas_frankel