O slideshow foi denunciado.
Seu SlideShare está sendo baixado. ×

Testing with JUnit 5 and Spring - Spring I/O 2022

Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Próximos SlideShares
Testing with JUnit 5 and Spring
Testing with JUnit 5 and Spring
Carregando em…3
×

Confira estes a seguir

1 de 44 Anúncio

Testing with JUnit 5 and Spring - Spring I/O 2022

Baixar para ler offline

This session will give you an overview of the latest and greatest in the world of testing using JUnit Jupiter (a.k.a. JUnit 5) and the Spring Framework.

The focus will be major new features in JUnit Jupiter 5.8 and 5.9 as well as recent and upcoming enhancements to Spring's integration testing support.

This session will give you an overview of the latest and greatest in the world of testing using JUnit Jupiter (a.k.a. JUnit 5) and the Spring Framework.

The focus will be major new features in JUnit Jupiter 5.8 and 5.9 as well as recent and upcoming enhancements to Spring's integration testing support.

Anúncio
Anúncio

Mais Conteúdo rRelacionado

Semelhante a Testing with JUnit 5 and Spring - Spring I/O 2022 (20)

Mais de Sam Brannen (20)

Anúncio

Mais recentes (20)

Testing with JUnit 5 and Spring - Spring I/O 2022

  1. 1. Sam Brannen @sam_brannen Spring I/O 2022 Testing with and Copyright © 2022 VMware, Inc. or its affiliates. JUnit
  2. 2. ©2020 VMware, Inc. 2 This presentation may contain product features or functionality that are currently under development. This overview of new technology represents no commitment from VMware to deliver these features in any generally available product. Features are subject to change, and must not be included in contracts, purchase orders, or sales agreements of any kind. Technical feasibility and market demand will affect final delivery. Pricing and packaging for any new features/functionality/technology discussed or presented, have not been determined. The information in this presentation is for informational purposes only and may not be incorporated into any contract. There is no commitment or obligation to deliver any items presented herein. Disclaimer
  3. 3. Sam Brannen ● Staff Software Engineer ● Java Developer for over 20 years ● Spring Framework Core Committer since 2007 ● JUnit 5 Core Committer since October 2015
  4. 4. Cover w/ Image Agenda ● JUnit 5.8 ● JUnit 5.9 ● Spring 5.3 ● Spring 6.0 ● Q&A
  5. 5. JUnit Jupiter Support in Spring JUnit Jupiter and Spring are a great match for testing ● Spring Framework ● @ExtendWith(SpringExtension.class) ● @SpringJUnitConfig ● @SpringJUnitWebConfig ● Spring Boot ● @SpringBootTest ● @WebMvcTest, etc.
  6. 6. JUnit 5.8
  7. 7. Major Features in JUnit Platform 1.8 ● Declarative test suites via @Suite classes ● SuiteTestEngine in junit-platform-suite-engine module ● new annotations in junit-platform-suite-api module ■ @Suite, @ConfigurationParameter, @SelectUris, @SelectFile, etc. ● UniqueIdTrackingListener ○ TestExecutionListener that tracks the unique IDs of all tests ○ generates a file containing the unique IDs ○ can be used to rerun those tests  ■ for example, with GraalVM Native Build Tools
  8. 8. Example: Suites before 5.8 – Now Deprecated // Uses JUnit 4 to run JUnit 5 @RunWith(JUnitPlatform.class) @SuiteDisplayName("Integration Tests") @IncludeEngines("junit-jupiter") @SelectPackages("com.example") @IncludeTags("integration-test") public class IntegrationTestSuite { }
  9. 9. Example: Suites with JUnit 5.8 // Uses JUnit 5 to run JUnit 5 @Suite @SuiteDisplayName("Integration Tests") @IncludeEngines("junit-jupiter") @SelectPackages("com.example") @IncludeTags("integration-test") public class IntegrationTestSuite { }
  10. 10. Small Enhancements in JUnit 5.8 https://junit.org/junit5/docs/5.8.0/release-notes/ ● More fine-grained Java Flight Recorder (JFR) events ● plus support on Java 8 update 262 or higher ● assertThrowsExactly() ○ alternative to assertThrows() ● assertInstanceOf() ○ instead of assertTrue(obj instanceof X) ● @RegisterExtension fields may now be private
  11. 11. New in JUnit Jupiter 5.8
  12. 12. Test Class Execution Order ● ClassOrderer API analogous to the MethodOrderer API ○ ClassName ○ DisplayName ○ OrderAnnotation ○ Random ● Global configuration via junit.jupiter.testclass.order.default configuration parameter for all test classes ● for example, to optimize the build ● Local configuration via @TestClassOrder for @Nested test classes
  13. 13. Example: @TestClassOrder @TestClassOrder(ClassOrderer.OrderAnnotation.class) class OrderedNestedTests { @Nested @Order(1) class PrimaryTests { @Test void test1() {} } @Nested @Order(2) class SecondaryTests { @Test void test2() {} } }
  14. 14. @TempDir – New Behavior Due to popular demand from the community… ● @TempDir previously created a single temporary directory per context ● @TempDir can now be used to create multiple temporary directories ● JUnit now creates a separate temporary directory per @TempDir annotation ● Revert to the old behavior by setting the junit.jupiter.tempdir.scope configuration parameter to per_context
  15. 15. @ExtendWith on Fields and Parameters Improves programming model ● @RegisterExtension: register extensions via fields programmatically ○ nothing new ● @ExtendWith: can now register extensions via fields and parameters declaratively ● fields: static or instance ● parameters: constructor, lifecycle method, test method ● typically as a meta-annotation ● avoids the need to declare @ExtendWith at the class or method level
  16. 16. Example: RandomNumberExtension @Target({ ElementType.FIELD, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @ExtendWith(RandomNumberExtension.class) public @interface Random { } class RandomNumberExtension implements BeforeAllCallback, BeforeEachCallback, ParameterResolver { // implementation... }
  17. 17. Example: @Random in Action class RandomNumberTests { @Random private int randomNumber1; RandomNumberTests(@Random int randomNumber2) { } @BeforeEach void beforeEach(@Random int randomNumber3) { } @Test void test(@Random int randomNumber4) { } }
  18. 18. Named API ● Named: container that associates a name with a given payload ○ The meaning of the payload depends on the context ○ Named.of() vs. Named.named() ● DynamicTests.stream() can consume Named input and will use each name-value pair as the display name and value for each generated dynamic test ● In parameterized tests using @MethodSource or @ArgumentSource, arguments can now have explicit names supplied via the Named API ○ explicit name used in display name instead of the argument value
  19. 19. Example: Named Dynamic Tests @TestFactory Stream<DynamicTest> dynamicTests() { Stream<Named<String>> inputStream = Stream.of( named("racecar is a palindrome", "racecar"), named("radar is also a palindrome", "radar"), named("mom also seems to be a palindrome", "mom"), named("dad is yet another palindrome", "dad") ); return DynamicTest.stream(inputStream, text -> assertTrue(isPalindrome(text))); }
  20. 20. AutoCloseable Arguments in Parameterized Tests ● In parameterized tests, arguments that implement AutoCloseable will now be automatically closed after the test completes ● Allows for automatic cleanup of resources ○ closing a file ○ stopping a server ○ etc. ● Similar to the CloseableResource support in the ExtensionContext.Store
  21. 21. Small Enhancements in JUnit Jupiter 5.8.x https://junit.org/junit5/docs/5.8.2/release-notes/ ● Support for text blocks in @CsvSource ● CSV headers in display names for @CsvSource and @CsvFileSource ● Custom quote character support in @CsvSource and @CsvFileSource ● Java 18 support in the JRE enum ● Access to the ExecutionMode in the ExtensionContext
  22. 22. Example: @CsvSource Before Text Blocks @ParameterizedTest @CsvSource({ "apple, 1", "banana, 2", "'lemon, lime', 0xF1", "strawberry, 700_000" }) void testWithCsvSource(String fruit, int rank) { assertNotNull(fruit); assertNotEquals(0, rank); }
  23. 23. Example: @CsvSource with Text Blocks @ParameterizedTest @CsvSource(quoteCharacter = '"', textBlock = """ # FRUIT, RANK apple, 1 banana, 2 "lemon, lime", 0xF1 strawberry, 700_000 """) void testWithCsvSource(String fruit, int rank) { assertNotNull(fruit); assertNotEquals(0, rank); }
  24. 24. Example: @CsvSource with CSV Headers @ParameterizedTest(name = "[{index}] {arguments}") @CsvSource(useHeadersInDisplayName = true, textBlock = """ FRUIT, RANK apple, 1 banana, 2 'lemon, lime', 0xF1 strawberry, 700_000 """) void testWithCsvSource(String fruit, int rank) { assertNotNull(fruit); assertNotEquals(0, rank); }
  25. 25. JUnit 5.9
  26. 26. JUnit Platform 1.9 M1 https://junit.org/junit5/docs/5.9.0-M1/release-notes/ ● XML reports in new Open Test Reporting format ○ https://github.com/ota4j-team/open-test-reporting ● New IterationSelector ○ for selecting a subset of a test’s or container’s iterations ● Various improvements to ConsoleLauncher ○ --single-color and --color-palette ○ --list-engines ○ JUnit Platform Suite Engine included in stand-alone JAR
  27. 27. JUnit Jupiter 5.9 M1 ● Configurable cleanup mode for @TempDir ○ ALWAYS, ON_SUCCESS, NEVER ● New TestInstancePreConstructCallback extension API ○ counterpart to existing TestInstancePreDestroyCallback ● Reusable parameter resolution for custom extension methods via ExecutableInvoker API ○ accessed via ExtensionContext ○ @BeforeTransaction / @AfterTransaction in Spring? ● @MethodSource factory methods can accept arguments ○ resolved by ParameterResolver extensions
  28. 28. DEMO @MethodSource and Spring
  29. 29. Spring Framework 5.3
  30. 30. New in Spring Framework 5.3.x (1/2) https://github.com/spring-projects/spring-framework/releases ● Test configuration is now discovered on enclosing classes for @Nested test classes ● ApplicationEvents abstraction for capturing application events published in the ApplicationContext during a test ● Set spring.test.constructor.autowire.mode in junit-platform.properties ● Detection for @Autowired violations in JUnit Jupiter ● Improvements for file uploads and multipart support in MockMvc and MockRestServiceServer ● Various enhancements in MockHttpServletRequest and MockHttpServletResponse
  31. 31. New in Spring Framework 5.3.x (2/2) ● Improved SQL script parsing regarding delimiters and comments ● ExceptionCollector testing utility ● Soft assertions for MockMvc and WebTestClient ● Support for HtmlFileInput.setData() with HtmlUnit and MockMvc ● setDefaultCharacterEncoding() in MockHttpServletResponse ● Default character encoding for responses in MockMvc
  32. 32. Tip: Use Text Blocks... Where you can ● @Sql(statements = …) ○ Just works ● Maybe other places in Spring as well ● Maybe in other frameworks
  33. 33. Example: @Nested tests before 5.3 @SpringJUnitConfig(TestConfig.class) @ActiveProfiles("dev") @Transactional class DevTests { @Nested @SpringJUnitConfig(TestConfig.class) @ActiveProfiles("dev") @Transactional class OrderTests { /* tests */ } @Nested @SpringJUnitConfig(PricingConfig.class) class PricingTests { /* tests */ } }
  34. 34. Example: @Nested tests after 5.3 @SpringJUnitConfig(TestConfig.class) @ActiveProfiles("dev") @Transactional class DevTests { @Nested class OrderTests { /* tests */ } @Nested @NestedTestConfiguration(OVERRIDE) @SpringJUnitConfig(PricingConfig.class) class PricingTests { /* tests */ } }
  35. 35. Example: ApplicationEvents @SpringJUnitConfig(/* ... */) @RecordApplicationEvents class OrderServiceTests { @Autowired OrderService orderService; @Autowired ApplicationEvents events; @Test void submitOrder() { // Invoke method in OrderService that publishes an event orderService.submitOrder(new Order(/* ... */)); // Verify that 1 OrderSubmitted event was published assertThat(events.stream(OrderSubmitted.class)).hasSize(1); } }
  36. 36. Example: MockMvc without Soft Assertions mockMvc.perform(get("/person/5").accept(APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value("Jane"));
  37. 37. Example: MockMvc with Soft Assertions mockMvc.perform(get("/person/5").accept(APPLICATION_JSON)) .andExpectAll( status().isOk(), jsonPath("$.name").value("Jane") );
  38. 38. Example: WebTestClient without Soft Assertions webTestClient.get().uri("/test").exchange() .expectStatus().isOk() .expectBody(String.class).isEqualTo("hello");
  39. 39. Example: WebTestClient with Soft Assertions webTestClient.get().uri("/test").exchange() .expectAll( spec -> spec.expectStatus().isOk(), spec -> spec.expectBody(String.class).isEqualTo("hello") );
  40. 40. Example: MockMvc default response character encoding MockMvc mockMvc; @BeforeEach void setup(WebApplicationContext wac) { this.mockMvc = webAppContextSetup(wac) .defaultResponseCharacterEncoding(StandardCharsets.UTF_8) .build(); } @Test void getPerson() throws Exception { this.mockMvc.perform(get("/person/1").characterEncoding(UTF_8)) .andExpect(status().isOk()) .andExpect(content().encoding(UTF_8)); }
  41. 41. Spring Framework 6.0
  42. 42. Testing Enhancements in Spring 6.0 ● Module path scanning support ○ for example, when using Maven Surefire and patched modules ○ https://github.com/sbrannen/spring-module-system ● Mechanism for avoiding repeated attempts to load a failing ApplicationContext ○ likely with configurable number of retries ● Accept arguments in @BeforeTransaction and @AfterTransaction methods ● Otherwise, not much else currently planned for 6.0 GA ○ rather for 6.0.x
  43. 43. Q&A
  44. 44. Thank you Twitter: @sam_brannen © 2022 Spring. A VMware-backed project. and JUnit

×