Speaker: Sam Brannen
Twitter: @sam_brannen
Agenda
- Spring Events App
- Spring 4.3
- JUnit 5
- Spring 5
Spring Events App
The Spring Events App is a Spring boot powered web app using
Spring Boot 1.4, Spring Framework 5, JUnit 5.
- Simple PJO Domain model: Event
- Transactional service layer
- Spring Data JPA
- Spring MV
- github.com/sbrannen/spring-events
Odds & Ends
- JUnit 4.12+ required by the Spring TestContext framework (TCF)
- Support for Primary transaction managers and data sources in TCF
- @Sql and @Sqlgroup many now be used as meta-annotations:
- to create custom composed annotations with attribute overrides
- Same is true for many @Repeatable annotations in Core Spring
- ReflectionTestUtils automatically unwraps proxies when setting/getting a field
Extending the Spring TextContext Framework
- The getTestContext() method in TestContextManager is now public
- New ContextCustomizer and ContextCustomizerFactory SPIs
- Potentially replaces need for custom ContextLoader
- Customize ApplicationContext after bean definitions are loaded but before context is refreshed
- Registered globally by third parties via spring.factories mechanism
- Enables Spring Boot Test Magic
New Features
- SpringRunner alias for the SpringJUnit4ClassRunner
>> @RunWith(SpringRunner.class) - @ContextConfiguration can be completely omitted…
- if default XML or @Configuration is detected
- Spring Boot test 1.4 even locates your @SpringBootApplication class
- ApplicationContext cache is now bounded
Preparing for the Future
- Testing Traits
- Spring test annotations can be declared on interfaces
- Combines nicely with Java 8 default methods and JUnit 5
- Non-public @Transactional test methods: for use with JUnit 5 and TestNG
- Non-public @BeforeTransaction and @AfterTransaction methods
MockMvc Improvements
- Expectations on multi-value response headers: HeaderResultMatchers.stringValues(…)
- Form data equest content (e.g., from a POST) now parsed and used to populate request params
- Support for Custom HTTP verbs (e.g. WebDAV)
- Improve Cookie support for HtmlUnit integration
MockMvc – Assert invoked Handler Method
New mock-like methodCall() assertion in HandlerResultMatchers: Assert the @Controller method invoked to handle the response:
mockMvc.perform(get("/")) .andExpect(handler().methodCall( on(HomeController.class).showHomePage()));
MockMvc – JSON Prefixes
New support for stripping JSON prefixes from Responses. A prefix is used to prohibit JSON hijacking:
mockMvc.perform(get("/account/42").accept(APPLICATION_JSON)) .andExpect(jsonPath("$.pin") .prefix("&&enigma&&") ...
MockRestServiceServer Improvements
- Expectations for form data in the request body
- Specify expectation counts
- Pass ExpectedCount to the expect() method
- once(), manyTimes(), times(int), min(int), max(int), between(int, int)
- verify() and reset() afterwards
- Specify whether ordering should be ignored: invoke ignoreExpectOrder(true) on the MockResetServiceServerBuilder
JUnit 5: Impetus for Change
- JUnit 4.0 was released a decade ago
- Modularity -> big ball of mud (i.e., only THE junit.jar)
- Test Discovery and execution -> tightly coupled
- Extensibility -> lot of room for improvement
- Java 8 support
JUnit 4 Runner API
- Very Powerful
- You can do anything
- But you cannot combine Runners
- Parameterized + SpringJUnit4ClassRunner -> no way
JUnit 4… Rules… are meant to be broken
- JUnit 4.7: MethodRule -> @Rule
- JUnit 4.9: TestRule -> @Rule/@ClassRule
JUnit Lambda
- Initiated by Johannes Link and Marc Philipp
- Later joined by Matthias Merdes, Stefan Bechtold, and Sam Brannen
JUnit 5 – Roadmap
- Prototype – December 2015
- Alpha – February 2016
- M1 & M2 – July 2016
- M3, M4, RC1 – Fall 2016
- GA – End of 2016… maybe
JUnit 5 – In a Nutshell
- Modular
- Extensible
- Modern
- Forward & Backward Compatible
- JUnit Platform supports JUnit 3.8, 4 and 5
- New testing frameworks can be run with JUnit 4 infrastructure:
@RunWith(JUnitPlatform.class)
JUnit 5 = Platform + Jupiter + Vintage
- JUnit Platform 1.0.0
- Foundation for launching testing frameworks on the JVM
- Launcher and TestEngine APIs
- ConsoleLauncher, Gradle Plugin, Maven Surefire provider
- JUnit Jupiter 5.0.0: New programming model and extension model for JUnit 5
- JUnit Vintage 4.12.0: TestEngine for running old stuff
Launcher API
- Used by IDEs and build tools to launch the framework
- Central API for discovering and executing tests via one or more engines
- LauncherDiscoveryRequest: Selectors and filters
- Feedback provided via the TestExecutionListener API
TestEngine API
- aka, Runner in JUnit 4
- Test engine discovers and executes tests for a particular programming model
- Automatic registration via Java’s ServiceLoader mechanism
- JupiterTestEngine
- VintageTestEngine
- Implement your own…
Extension APIs
- BeforeAllCallback
- BeforeEachCallback
- BeforeTestExecutionCallback
- AfterTestExecutionCallback
- AfterEachCallback
- AfterAllCallback
- ContainerExecutionCondition & TestExecutionCondition
- TestInstancePostProcessor
- ParameterResolver
- TestExecutionExceptionHandler
JUnit 5 – Programming Model
org.junit.jupiter.api
- Annotations & Meta-annotations
- Assertions & Assumptions
- Custom Display Names
- Visibility
- Tagging
- Conditional Test Execution
- DI for Constructors and methods
- Lambda Expressions and method references
- Interface default methods
- Nested test classes
- Dynamic Tests
Annotations
- @Test / @TestFactory
- @BeforeAll / @AfterAll
- @BeforeEach / @AfterEach
- @DisplayName
- @Tag
- @Disabled
- @Nested
Assertions
org.junit.jupiter.api.Assertions
- Limited set of core assertions
- assertThrows() and expectThrows()
- assertTimeout()
- assertAll()