3,
JUnit 5, and beyond ...
Sam Brannen
@sam_brannen
Sam Brannen
• Spring and Java Consultant @
3
Agenda
• Spring Events App
• Spring 4.3
• JUnit 5
• Spring 5
• Q&A
4
Show of hands …
5
Spring Events App
6
The Spring Events Example Application
• Spring Boot powered web app
• Spring Boot 1.4, Spring Framework 5, JUnit 5
• Spring Security
• https://github.com/sbrannen/spring-events
7
New in Spring Framework 4.3
8
Odds & Ends
• JUnit 4.12+ required by the Spring TestContext Framework (TCF)
• Support for primary transaction managers and data sources in the TCF
9
Extending the Spring TestContext Framework
• The getTestContext() method in TestContextManager is now public
10
New Features
• SpringRunner alias for the SpringJUnit4ClassRunner
• @RunWith(SpringRunner.class)
11
Demo
SpringRunner, @ContextConfiguration, bounded cache
12
Preparing for the Future
• Testing Traits
• Spring test annotations can be declared on interfaces
• Combines nicely with Java 8 default methods and JUnit 5
• Enabling so called testing traits in Java
13
MockMvc Improvements
• Expectations on multi-value response headers
• HeaderResultMatchers.stringValues(String, String...)
• Form data request content (e.g., from a POST) is now parsed and used to
populate request parameters
14
MockMvc – Assert Invoked Handler Method
• New mock-like methodCall() assertion in HandlerResultMatchers
• Assert the @Controller method invoked to handle the response
• Uses MvcUriComponentsBuilder under the hood
mockMvc.perform(get("/"))
.andExpect(handler().methodCall(
on(HomeController.class).showHomePage()));
15
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&&")
.value("1234"));
16
MockRestServiceServer Improvements
• Expectations for form data in the request body
• ContentRequestMatchers.formData(MultiValueMap<String, String>)
17
JUnit 5
18
Impetus for Change
• JUnit 4.0 was released a decade ago
• a lot has changed since then…
• testing needs have matured
• expectations have grown
• But… a single rule can’t be used for method-level and class-level callbacks
• Plus… zero support for instance-level callbacks
• Extensible
• Modern
• Central API for discovering and executing tests via one or more engines
• LauncherDiscoveryRequest
• selectors and filters
• JupiterTestEngine
• VintageTestEngine
P L A T F O R M
T H I R D
P A R T Y P L A T F O R M
J U P I T E R
V I N T A G E
JUnit 5 – Extension Model
• Extension
• marker interface
• org.junit.jupiter.api.extension
• package containing all extension APIs
• implement as many as you like
• @ExtendWith(...)
• used to register one or more extensions
• interface, class, or method level
o or as a meta-annotation
Extension APIs
• BeforeAllCallback
• BeforeEachCallback
o BeforeTestExecutionCallback
o AfterTestExecutionCallback
• AfterEachCallback
• AfterAllCallback
• @DisplayName
• @Tag
• @Disabled
• @Nested
Assertions
org.junit.jupiter.api.Assertions
• assumeTrue() / assumeFalse()
• BooleanSupplier, Supplier<String>
• assumingThat( ? , () -> {} );
Demo
basic tests and assertions
38
Test Names
• Names default to test class or test method names
• characters limited based on Java syntax
• ParameterResolver extension
• resolves parameters for constructors or methods
• TestInfoParameterResolver
• eating our own dog food ;-)
• See also:
• TestReporter
• MockitoExtension
• SpringExtension
Demo
display names and dependency injection
41
Tagging
• Declare @Tag on a test interface, class, or method
@Tag("fast")
@Test
void myFastTest() {
}
Custom Tags
• Declare @Tag as a meta-annotation
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Tag("fast")
@Test
public @interface FastTest {
}
@FastTest
void myFastTest() {
}
Conditional Test Execution
• Extension Model meets Programming Model
• ContainerExecutionCondition
• TestExecutionCondition
• @Disabled
• DisabledCondition
• eating our own dog food ;-)
• @BeforeEach / @AfterEach
• @Test
• @Tag
• @ExtendWith
48
What’s Missing?
• Official IDE and build integration
• IntelliJ IDEA 2016.2: beta support
• Eclipse: on the radar, but not until 2017
• Gradle & Maven: interim solutions from JUnit Team
• Parameterized tests
• Scenario tests
• Parallel execution
• …
New in Spring Framework 5.0
50
Spring Support for JUnit 5
• Fully integrated in Spring Framework 5.0 M1
• Supports all Core Spring TestContext Framework features
• Constructor and method injection via @Autowired, @Qualifier, @Value
• SpringExtension
• @ExtendWith(SpringExtension.class)
52
Spring Boot 1.4 + JUnit 5 – Custom Config
• @SpringBootTest + @AutoConfigureMockMvc +
@ExtendWith(SpringExtension.class)
@Target(TYPE)
@Retention(RUNTIME)
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = MOCK)
@AutoConfigureMockMvc
@Transactional
public @interface SpringEventsWebTest {
}
Spring Boot 1.4 + JUnit 5 – MockMvc Test
• @SpringEventsWebTest + method-level DI + MockMvc
@SpringEventsWebTest
class EventsControllerTests {
@Test
@DisplayName("Home page should display more than 10 events")
void listEvents(@Autowired MockMvc mockMvc) throws Exception {
mockMvc.perform(get("/"))
.andExpect(view().name("event/list"))
.andExpect(model().attribute("events",
hasSize(greaterThan(10))));
}
}
In closing …
55
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, …
56
JUnit 5 Resources
Project Homepage
http://junit.org/junit5
User Guide
http://junit.org/junit5/docs/current/user-guide
Javadoc
http://junit.org/junit5/docs/current/api
GitHub
https://github.com/junit-team/junit5
https://github.com/junit-team/junit5-samples
Stack Overflow
http://stackoverflow.com/tags/junit5
57
Blogs
Spring Blog
http://spring.io/blog
Swiftmind Blog
http://www.swiftmind.com/blog
58
Q&A
Sam Brannen