Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

8,658 views

Published on

SpringOne Platform 2016
Speaker: Sam Brannen; Co-Founder, Swiftmind

Curious about what's new in Spring's testing support in 4.3 or what's on the horizon in Spring 5 and JUnit 5? Then join Sam Brannen, Spring Test component lead and JUnit 5 core committer, to find out! The first part of this session will give attendees an overview of the latest core integration testing improvements in Spring 4.3 such as the new SpringRunner alias for the SpringJUnit4ClassRunner, the omission of @ContextConfiguration when it can be inferred, support for @Sql and @SqlGroup as composed annotations, limiting the context cache size within a test suite, and the new ContextCustomizer API for customizing a test's ApplicationContext. The next part will cover recent improvements in Spring MVC Test such as server-side testing support for expectations on response headers, form data processing, JSON prefixes in response content, custom HTTP verbs, and verifying that a specific controller method was invoked as well as client-side REST testing support for indicating how many times a request is expected and expectations for form data in the request body. The focus will then shift to what kinds of testing features to expect in Spring 5.0. And last, but certainly not least, Sam will dive into live examples using Spring's upcoming support for JUnit 5 for modern testing on Java 8 and beyond.

Published in: Technology

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

  1. 1. Testing with Spring 4.3, JUnit 5, and beyond ... Sam Brannen @sam_brannen
  2. 2. 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
  3. 3. 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
  4. 4. Agenda • Spring Events App • Spring 4.3 • JUnit 5 • Spring 5 • Q & A 4
  5. 5. Show of hands … 5
  6. 6. Spring Events App 6
  7. 7. 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
  8. 8. New in Spring Framework 4.3 8
  9. 9. 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
  10. 10. 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
  11. 11. 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 property 11
  12. 12. Demo 12 SpringRunner, @ContextConfiguration, bounded cache
  13. 13. 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
  14. 14. 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
  15. 15. 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()));
  16. 16. 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"));
  17. 17. 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
  18. 18. JUnit 5 18
  19. 19. 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
  20. 20. JUnit 4 Runner API • Very powerful • In fact, it can do anything • But… you can’t combine Runners • Parameterized + SpringJUnit4ClassRunner  no way
  21. 21. 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
  22. 22. 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
  23. 23. Thanks!
  24. 24. The Kick-off Team
  25. 25. 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
  26. 26. 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)
  27. 27. 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
  28. 28. 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
  29. 29. 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…
  30. 30. 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 Y T H I R D
  31. 31. PLATFORM JUPITER VINTAGE PARTY THIRD
  32. 32. 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
  33. 33. Extension APIs • BeforeAllCallback • BeforeEachCallback o BeforeTestExecutionCallback o AfterTestExecutionCallback • AfterEachCallback • AfterAllCallback • ContainerExecutionCondition & TestExecutionCondition • TestInstancePostProcessor • ParameterResolver • TestExecutionExceptionHandler
  34. 34. JUnit 5 – Programming Model org.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
  35. 35. Annotations • @Test / @TestFactory • @BeforeAll / @AfterAll • @BeforeEach / @AfterEach • @DisplayName • @Tag • @Disabled • @Nested
  36. 36. Assertions org.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.
  37. 37. Assumptions org.junit.jupiter.api.Assumptions • Limited set of core assumptions • For aborting tests mid-flight • assumeTrue() / assumeFalse() • BooleanSupplier, Supplier<String> • assumingThat( ? , () -> {} );
  38. 38. Demo 38 basic tests and assertions
  39. 39. 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 😱
  40. 40. 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
  41. 41. Demo 41 display names and dependency injection
  42. 42. Tagging @Tag("fast") @Test void myFastTest() { } • Declare @Tag on a test interface, class, or method
  43. 43. Custom Tags @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Tag("fast") @Test public @interface FastTest { } • Declare @Tag as a meta-annotation @FastTest void myFastTest() { }
  44. 44. 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.*
  45. 45. 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
  46. 46. 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
  47. 47. Dynamic Tests • Conventional tests are static (i.e., known at compile time) o @Test methods • A DynamicTest is registered at run time o as lambda expression in a stream, collection, etc. o by a method annotated with @TestFactory • Somewhat analogous to parameterized tests
  48. 48. Demo 48 dynamic tests
  49. 49. 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 • …
  50. 50. New in Spring Framework 5.0 50
  51. 51. 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
  52. 52. Demo 52 Spring 5 and JUnit 5
  53. 53. Spring Boot 1.4 + JUnit 5 – Custom Config @Target(TYPE) @Retention(RUNTIME) @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = MOCK) @AutoConfigureMockMvc @Transactional public @interface SpringEventsWebTest { } • @SpringBootTest + @AutoConfigureMockMvc + @ExtendWith(SpringExtension.class)
  54. 54. Spring Boot 1.4 + JUnit 5 – MockMvc Test @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)))); } } • @SpringEventsWebTest + method-level DI + MockMvc
  55. 55. In closing … 55
  56. 56. 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
  57. 57. 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
  58. 58. Blogs Spring Blog http://spring.io/blog Swiftmind Blog http://www.swiftmind.com/blog 58
  59. 59. Q & A Sam Brannen @Sam_Brannen slideshare.net/sbrannen @SpringCentral spring.io @JUnitTeam junit.org/junit5

×