testing with spring 4.3, junit 5, and beyond

59
Testing with Spring 4.3, JUnit 5, and beyond ... Sam Brannen @sam_brannen

Upload: spring-by-pivotal

Post on 16-Apr-2017

3.244 views

Category:

Technology


6 download

TRANSCRIPT

Page 1: Testing with Spring 4.3, JUnit 5, and Beyond

Testing with Spring 4.3,JUnit 5, and beyond ...

Sam Brannen@sam_brannen

Page 2: Testing with Spring 4.3, JUnit 5, and Beyond

Sam Brannen• Spring and Java Consultant @

• Java Developer for over 17 years

• Spring Framework Core Committer since 2007

• Swiss Spring User Group Lead

• Trainer & Conference Speaker

• JUnit 5 Core Committer since October 2015

Page 3: Testing with Spring 4.3, JUnit 5, and Beyond

3

Your experts for Spring and Enterprise Java

Areas of expertise• Spring *• JUnit• Java EE• Software Architecture• Code Reviews

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

www.swiftmind.com

Page 4: Testing with Spring 4.3, JUnit 5, and Beyond

Agenda• Spring Events App

• Spring 4.3

• JUnit 5

• Spring 5

• Q & A

4

Page 5: Testing with Spring 4.3, JUnit 5, and Beyond

Show of hands …

5

Page 6: Testing with Spring 4.3, JUnit 5, and Beyond

Spring Events App

6

Page 7: Testing with Spring 4.3, JUnit 5, and Beyond

The Spring Events Example Application• Spring Boot powered web app

• Spring Boot 1.4, Spring Framework 5, JUnit 5

• 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

7

Page 8: Testing with Spring 4.3, JUnit 5, and Beyond

New in Spring Framework 4.3

8

Page 9: Testing with Spring 4.3, JUnit 5, and Beyond

Odds & Ends• JUnit 4.12+ required by the Spring TestContext Framework (TCF)

• Support for primary transaction managers and data sources in the TCF

• @Sql and @SqlGroup may 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

9

Page 10: Testing with Spring 4.3, JUnit 5, and Beyond

Extending the Spring TestContext 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 the context is refreshed• Registered globally by third parties via spring.factories mechanism• Enables Spring Boot Test magic• Implement to create your own magic

10

Page 11: Testing with Spring 4.3, JUnit 5, and Beyond

New Features• SpringRunner alias for the SpringJUnit4ClassRunner

• @RunWith(SpringRunner.class)

• @ContextConfiguration can be completely omitted…• if default XML, Groovy, or @Configuration is detected• Spring Boot Test 1.4 even locates your @SpringBootApplication class

• ApplicationContext cache is now bounded• default maximum size of 32• Least Recently Used eviction policy• configured via spring.test.context.cache.maxSize JVM/Spring

property11

Page 12: Testing with Spring 4.3, JUnit 5, and Beyond

Demo

12

SpringRunner, @ContextConfiguration, bounded cache

Page 13: Testing with Spring 4.3, JUnit 5, and Beyond

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

• Non-public @Transactional test methods• For use with JUnit 5 and TestNG

• Non-public @BeforeTransaction and @AfterTransaction methods• can also be declared on default methods to create testing traits

13

Page 14: Testing with Spring 4.3, JUnit 5, and Beyond

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

• Support for custom HTTP verbs (e.g., WebDAV)• MockMvcRequestBuilders.request(String methodName, URI uri)

• Improved Cookie support for HtmlUnit integration

14

Page 15: Testing with Spring 4.3, JUnit 5, and Beyond

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

15

mockMvc.perform(get("/")) .andExpect(handler().methodCall( on(HomeController.class).showHomePage()));

Page 16: Testing with Spring 4.3, JUnit 5, and Beyond

MockMvc – JSON Prefixes• New support for stripping JSON prefixes from responses

• a prefix is used to prohibit JSON Hijacking

16

mockMvc.perform(get("/account/42").accept(APPLICATION_JSON)) .andExpect(jsonPath("$.pin") .prefix("&&enigma&&") .value("1234"));

Page 17: Testing with Spring 4.3, JUnit 5, and Beyond

MockRestServiceServer Improvements• Expectations for form data in the request body

• ContentRequestMatchers.formData(MultiValueMap<String, String>)

• 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 MockRestServiceServerBuilder • MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build();

17

Page 18: Testing with Spring 4.3, JUnit 5, and Beyond

JUnit 5

18

Page 19: Testing with Spring 4.3, JUnit 5, and Beyond

Impetus for Change• JUnit 4.0 was released a decade ago

• a lot has changed since then…• testing needs have matured• expectations have grown

• Modularity big ball of mud (i.e., only THE junit.jar)

• Test discovery and execution tightly coupled

• Extensibility lot of room for improvement

• Let’s not forget Java 8

Page 20: Testing with Spring 4.3, JUnit 5, and Beyond

JUnit 4 Runner API• Very powerful

• In fact, it can do anything

• But… you can’t combine Runners

• Parameterized + SpringJUnit4ClassRunner no way

Page 21: Testing with Spring 4.3, JUnit 5, and Beyond

JUnit 4… Rules… are meant to be broken• JUnit 4.7: MethodRule @Rule• JUnit 4.9: TestRule @Rule / @ClassRule

• Great for simple use cases• Can even be combined

• But… a single rule can’t be used for method-level and class-level callbacks

• Plus… zero support for instance-level callbacks

• Case in point: SpringClassRule / SpringMethodRule

Page 22: Testing with Spring 4.3, JUnit 5, and Beyond

JUnit Lambda – Crowdfunding Campaign• Initiated by Johannes Link and Marc Philipp

• Later joined by Matthias Merdes, Stefan Bechtold, & Sam Brannen

• Ran from July to October 2015

• Raised 53,937 Euros from 474 individuals and companies

• 4 companies donated 6 weeks of developer time

Page 23: Testing with Spring 4.3, JUnit 5, and Beyond

Thanks!

Page 24: Testing with Spring 4.3, JUnit 5, and Beyond

The Kick-off Team

Page 25: Testing with Spring 4.3, JUnit 5, and Beyond

JUnit 5 – Roadmap• Prototype December 2nd, 2015

• 5.0.0-ALPHA February 1st, 2016

• 5.0.0-M1 July 7th 2016

• 5.0.0-M2 July 23rd 2016

• M3, M4, RC1 Fall 2016

• GA end of 2016 ... maybe

Page 26: Testing with Spring 4.3, JUnit 5, and Beyond

JUnit 5 – in a Nutshell• Modular

• Extensible

• Modern

• Forward and backward compatible• JUnit Platform supports JUnit 3.8, JUnit 4, and JUnit 5• New testing frameworks can be run with JUnit 4 infrastructure

o @RunWith(JUnitPlatform.class)

Page 27: Testing with Spring 4.3, JUnit 5, and Beyond

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 JUnit 3 and JUnit 4 based tests

Page 28: Testing with Spring 4.3, JUnit 5, and Beyond

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

Page 29: Testing with Spring 4.3, JUnit 5, and Beyond

TestEngine API• Test engine discovers and executes tests

• for a particular programming model

• Automatic registration via Java’s ServiceLoader mechanism

• JupiterTestEngine

• VintageTestEngine

• Implement your own…

Page 30: Testing with Spring 4.3, JUnit 5, and Beyond

P L A T F O R M

J U P I T E RV I N T A G E P A R T YT H I R D

Page 31: Testing with Spring 4.3, JUnit 5, and Beyond

PL

AT

FO

RM

JU

PI

TE

R

VI

NT

AG

E

PA

RT

YT

HI

RD

Page 32: Testing with Spring 4.3, JUnit 5, and Beyond

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

Page 33: Testing with Spring 4.3, JUnit 5, and Beyond

Extension APIs• BeforeAllCallback

• BeforeEachCallbacko BeforeTestExecutionCallbacko AfterTestExecutionCallback

• AfterEachCallback• AfterAllCallback

• ContainerExecutionCondition & TestExecutionCondition• TestInstancePostProcessor• ParameterResolver• TestExecutionExceptionHandler

Page 34: Testing with Spring 4.3, JUnit 5, and Beyond

JUnit 5 – Programming Modelorg.junit.jupiter.api

• Annotations and meta-annotations• Assertions and Assumptions• Custom display names• Visibility• Tagging• Conditional test execution• Dependency injection for constructors and methods• Lambda expressions and method references• Interface default methods• Nested test classes• Dynamic tests

Page 35: Testing with Spring 4.3, JUnit 5, and Beyond

Annotations• @Test / @TestFactory• @BeforeAll / @AfterAll• @BeforeEach / @AfterEach

• @DisplayName

• @Tag

• @Disabled

• @Nested

Page 36: Testing with Spring 4.3, JUnit 5, and Beyond

Assertionsorg.junit.jupiter.api.Assertions

• Limited set of core assertions• assertEquals(), assertNotNull(), etc.• assertThrows() and expectThrows()• assertTimeout()• assertAll()

• Supplier<String> for lazy failure message evaluation• message is now the last parameter

• For more power, use AssertJ, Hamcrest, etc.

Page 37: Testing with Spring 4.3, JUnit 5, and Beyond

Assumptionsorg.junit.jupiter.api.Assumptions

• Limited set of core assumptions• For aborting tests mid-flight

• assumeTrue() / assumeFalse()• BooleanSupplier, Supplier<String>

• assumingThat( ? , () -> {} );

Page 38: Testing with Spring 4.3, JUnit 5, and Beyond

Demo

38

basic tests and assertions

Page 39: Testing with Spring 4.3, JUnit 5, and Beyond

Test Names• Names default to test class or test method names

• characters limited based on Java syntax

• Custom display names @DisplayName• Can contain spaces, special chars, and even emoji 😱

Page 40: Testing with Spring 4.3, JUnit 5, and Beyond

Dependency Injection• Extension Model meets Programming Model

• ParameterResolver extension• resolves parameters for constructors or methods

• TestInfo: inject into constructor, @Test, @BeforeEach, etc.• access display name, tags, class, method

• TestInfoParameterResolver• eating our own dog food ;-)

• See also:• TestReporter• MockitoExtension• SpringExtension

Page 41: Testing with Spring 4.3, JUnit 5, and Beyond

Demo

41

display names and dependency injection

Page 42: Testing with Spring 4.3, JUnit 5, and Beyond

Tagging

@Tag("fast")@Testvoid myFastTest() {}

• Declare @Tag on a test interface, class, or method

Page 43: Testing with Spring 4.3, JUnit 5, and Beyond

Custom Tags

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Tag("fast")@Testpublic @interface FastTest {}

• Declare @Tag as a meta-annotation

@FastTestvoid myFastTest() {}

Page 44: Testing with Spring 4.3, JUnit 5, and Beyond

Conditional Test Execution• Extension Model meets Programming Model

• ContainerExecutionCondition• TestExecutionCondition

• @Disabled• DisabledCondition

• eating our own dog food ;-)

• Deactivate via Launcher/System property• junit.conditions.deactivate = org.junit.*

Page 45: Testing with Spring 4.3, JUnit 5, and Beyond

Interface Default Methods• Introduces the concept of a test interface

• Enables multiple inheritance in tests• a.k.a., testing traits

• @BeforeEach / @AfterEach• @Test• @Tag• @ExtendWith

• See StringTests example in user guide

Page 46: Testing with Spring 4.3, JUnit 5, and Beyond

Nested Test Classes• Enables logical, hierarchical grouping of test classes

• with shared initialization and state from outer classes

• Declare @Nested on non-static nested classes• i.e., inner classes

• You can even combine nested classes and test interfaces

• See TestingAStack example in user guide

Page 47: Testing with Spring 4.3, JUnit 5, and Beyond

Dynamic Tests• Conventional tests are static (i.e., known at compile time)

o @Test methods

• A DynamicTest is registered at run timeo as lambda expression in a stream, collection, etc.o by a method annotated with @TestFactory

• Somewhat analogous to parameterized tests

Page 48: Testing with Spring 4.3, JUnit 5, and Beyond

Demo

48

dynamic tests

Page 49: Testing with Spring 4.3, JUnit 5, and Beyond

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

• …

Page 50: Testing with Spring 4.3, JUnit 5, and Beyond

New in Spring Framework 5.0

50

Page 51: Testing with Spring 4.3, JUnit 5, and Beyond

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

• Also works with Spring Framework 4.3• https://github.com/sbrannen/spring-test-junit5

• SpringExtension• @ExtendWith(SpringExtension.class)

• @SpringJUnitConfig and @SpringJUnitWebConfig

Page 52: Testing with Spring 4.3, JUnit 5, and Beyond

Demo

52

Spring 5 and JUnit 5

Page 53: Testing with Spring 4.3, JUnit 5, and Beyond

Spring Boot 1.4 + JUnit 5 – Custom Config

@Target(TYPE)@Retention(RUNTIME)

@ExtendWith(SpringExtension.class)@SpringBootTest(webEnvironment = MOCK)@AutoConfigureMockMvc@Transactionalpublic @interface SpringEventsWebTest {}

• @SpringBootTest + @AutoConfigureMockMvc + @ExtendWith(SpringExtension.class)

Page 54: Testing with Spring 4.3, JUnit 5, and Beyond

Spring Boot 1.4 + JUnit 5 – MockMvc Test

@SpringEventsWebTestclass 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)))); }}

• @SpringEventsWebTest + method-level DI + MockMvc

Page 55: Testing with Spring 4.3, JUnit 5, and Beyond

In closing …

55

Page 56: Testing with Spring 4.3, JUnit 5, and Beyond

Spring ResourcesSpring Frameworkhttp://projects.spring.io/spring-framework

Spring Guideshttp://spring.io/guides

Spring JIRAhttps://jira.spring.io

Spring on GitHubhttps://github.com/spring-projects/spring-framework

Stack Overflowspring, spring-test, spring-mvc, spring-boot, spring-security, …

56

Page 57: Testing with Spring 4.3, JUnit 5, and Beyond

JUnit 5 ResourcesProject Homepagehttp://junit.org/junit5

User Guidehttp://junit.org/junit5/docs/current/user-guide

Javadochttp://junit.org/junit5/docs/current/api

GitHubhttps://github.com/junit-team/junit5https://github.com/junit-team/junit5-samples

Stack Overflowhttp://stackoverflow.com/tags/junit5

57

Page 58: Testing with Spring 4.3, JUnit 5, and Beyond

Blogs

Spring Blog http://spring.io/blog

Swiftmind Blog http://www.swiftmind.com/blog

58

Page 59: Testing with Spring 4.3, JUnit 5, and Beyond

Q & ASam Brannen

@Sam_Brannenslideshare.net/sbrannen

@SpringCentralspring.io

@JUnitTeamjunit.org/junit5