Join core JUnit 5 committer Sam Brannen to gain insight on the latest new features in JUnit 5 as well as what’s on the horizon.
Sam will also provide tips on how to best use JUnit Jupiter to test Spring and Spring Boot apps.
2. 2@sam_brannen #JUnit5 #springio19
Sam Brannen
• Principal Software Engineer
• Java Developer for over 20 years
• Spring Framework Core Committer since 2007
• JUnit 5 Core Committer since October 2015
3. @sam_brannen #JUnit5 #springio19 3
Agenda
JUnit 5
JUnit Jupiter
Migrating from JUnit 4
New Features since 5.0
Roadmap
Spring and JUnit Jupiter
Q & A
6. 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
7. 7@sam_brannen #JUnit5 #springio19
JUnit 5 = Platform + Jupiter + Vintage
• JUnit Platform
• Foundation for launching testing frameworks on the JVM
• Launcher and TestEngine APIs
• ConsoleLauncher
• JUnit Jupiter
• New programming model & extension model for JUnit 5
• JUnit Vintage
• TestEngine for running JUnit 3 & JUnit 4 based tests
Revolutionary
Evolutionary
Necessary
8. 8@sam_brannen #JUnit5 #springio19
In a Nutshell, JUnit 5 is …
• Complete rewrite of JUnit
• Improving on what JUnit 4 had to offer
• With extensibility in mind
• Modular, Extensible, & Modern
• Forward and backward compatible
• JUnit Platform supports JUnit 3.8, JUnit 4, and JUnit Jupiter
• Plus support for any TestEngine imaginable
11. 11@sam_brannen #JUnit5 #springio19
IDEs and Build Tools
• IntelliJ: since IDEA 2016.2+
• Eclipse: since Eclipse Oxygen 4.7.1a+
• NetBeans: since Apache NetBeans 10.0
• Gradle: official test task support since Gradle 4.6
• Maven: official support since Maven Surefire 2.22.0
• Ant: junitlauncher task since Ant 1.10.3
See user guide and
sample apps for
examples
12. 12@sam_brannen #JUnit5 #springio19
Releases
Version Date
5.0.0 September 10th, 2017
5.1.0 February 18th, 2018
5.2.0 April 29th, 2018
5.3.0 September 3rd, 2018
5.4.0 February 7th, 2019
5.4.2 April 7th, 2019
14. 14@sam_brannen #JUnit5 #springio19
In a Nutshell, JUnit Jupiter is …
“The new programming model and extension model in JUnit 5”
• Programming Model
• How you write tests
• Annotations
• Assertions
• Assumptions
• Types of tests
• Extension Model
• How you and third parties extend the framework
• Spring, Mockito, Selenium, …
15. 15@sam_brannen #JUnit5 #springio19
More Powerful Programming Model
What you can do with JUnit Jupiter that you can’t do with JUnit 4.
• Visibility
• Everything does not have to be public
• Custom display names
• @DisplayName: spaces, special characters, emoji 😱
• DisplayNameGenerator (since 5.4)
• Tagging
• @Tag replaces experimental @Category
• Tag Expression Language (since 5.1)
20. 20@sam_brannen #JUnit5 #springio19
Even More Power and Expressiveness
• Meta-annotation support
• Create your own custom composed annotations
• Combine annotations from Spring and JUnit
• Conditional test execution
• Dependency injection for constructors and methods
• Lambda expressions and method references
• Interface default methods and testing traits
• @Nested test classes
• @RepeatedTest, @ParameterizedTest, @TestFactory
• @TestInstance lifecycle management
26. 26@sam_brannen #JUnit5 #springio19
@RepeatedTest
@RepeatedTest(5)
void repeatedTest(RepetitionInfo repetitionInfo) {
assertEquals(5, repetitionInfo.getTotalRepetitions());
}
@RepeatedTest(
value = 5,
name = "Wiederholung {currentRepetition} von {totalRepetitions}"
)
void repeatedTestInGerman() {
// ...
}
27. 27@sam_brannen #JUnit5 #springio19
Parameterized Tests (junit-jupiter-params)
• Annotate a method with @ParameterizedTest instead of @Test
o and specify the source of the arguments
o optionally override the display name
• Sources
o @ValueSource: char, short, byte, int, long, float, double, String, Class
o @NullSource, @EmptySource, and @NullAndEmptySource (since 5.4)
o @EnumSource
o @MethodSource
o @CsvSource & @CsvFileSource
o @ArgumentsSource & custom ArgumentsProvider
28. 28@sam_brannen #JUnit5 #springio19
Argument Conversion and Aggregation
• Implicit conversion
o Primitive types and their wrappers
o Enums
o File, URL, Currency, Locale, …
o java.time types (JSR-310)
o factory constructor or static factory method
• Explicit conversion
o @ConvertWith and custom ArgumentConverter
o @JavaTimeConversionPattern built-in support for JSR-310
• Argument Aggregation (since 5.2)
o Arguments and ArgumentAggregator
29. 29@sam_brannen #JUnit5 #springio19
@ParameterizedTest – @ValueSource
@ParameterizedTest
@ValueSource(strings = {
"mom",
"dad",
"radar",
"racecar",
"able was I ere I saw elba"
})
void palindromes(String candidate) {
assertTrue(isPalindrome(candidate));
}
30. 30@sam_brannen #JUnit5 #springio19
@ParameterizedTest – @MethodSource
@ParameterizedTest
@MethodSource // ("palindromes")
void palindromes(String candidate) {
assertTrue(isPalindrome(candidate));
}
static Stream<String> palindromes() {
return Stream.of("mom",
"dad",
"radar",
"racecar",
"able was I ere I saw elba");
}
31. 31@sam_brannen #JUnit5 #springio19
Dynamic Tests
@TestFactory
Stream<DynamicTest> dynamicTestsFromIntStream() {
// Generates tests for the first 10 even integers.
return IntStream.iterate(0, n -> n + 2)
.limit(10)
.mapToObj(n ->
dynamicTest("test" + n,
() -> assertTrue(n % 2 == 0)));
}
34. 34@sam_brannen #JUnit5 #springio19
Configuring Parallelism (5.3)
• Set junit.jupiter.execution.parallel.enabled config param to true
o in junit-platform.properties
o via Launcher API
o as JVM system property
• Configure the junit.jupiter.execution.parallel.config.strategy
o dynamic (the default)
o fixed
o custom
35. 35@sam_brannen #JUnit5 #springio19
Execution Mode and Synchronization (5.3)
• Disable parallel execution on a per test basis
o @Execution(SAME_THREAD) // or CONCURRENT
• Control synchronization
o @ResourceLock("myResource") // default READ_WRITE
o @ResourceLock(value = "myResource", mode = READ)
38. 38@sam_brannen #JUnit5 #springio19
New 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
• @RegisterExtension
• programmatic registration via fields (since 5.1)
41. 41@sam_brannen #JUnit5 #springio19
DisplayNameGenerator (5.4)
• SPI for generating custom display names for classes and methods
• Configured via @DisplayNameGeneration
• Implement your own
• Or use a built-in implementation:
• Standard: default behavior
• ReplaceUnderscores: replaces underscores with spaces
42. 42@sam_brannen #JUnit5 #springio19
MethodOrderer (5.4)
• API for controlling test method execution order
• Configured via @TestMethodOrder
• Implement your own
• Or use a built-in implementation:
• Alphanumeric: sorted alphanumerically
• OrderAnnotation: sorted based on @Order
• Random: pseudo-random ordering
44. 44@sam_brannen #JUnit5 #springio19
Conditional Test Execution
• Extension Model meets Programming Model
• ExecutionCondition
• @Disabled
• DisabledCondition
• eating our own dog food ;-)
• Deactivate via Launcher, JVM system property, or the
junit-platform.properties file
• junit.conditions.deactivate = org.junit.*
Game Changer
47. 47@sam_brannen #JUnit5 #springio19
Do I have to migrate from JUnit 4 to JUnit 5?
• Yes and No…
• You can run JUnit 4 tests on the JUnit Platform via the VintageTestEngine
• You can run JUnit 4 tests alongside JUnit Jupiter tests
o In the same project
• You can gradually migrate existing JUnit 4 tests to JUnit Jupiter
o if you want to
o or… you can just write all new tests in JUnit Jupiter
49. 49@sam_brannen #JUnit5 #springio19
JUnit 4 Rule Migration Support
• @EnableRuleMigrationSupport
o located in experimental junit-jupiter-migrationsupport module
o registers 3 extensions for JUnit Jupiter
• ExternalResourceSupport
o TemporaryFolder, etc.
• VerifierSupport
o ErrorCollector, etc.
• ExpectedExceptionSupport
o ExpectedException
50. 50@sam_brannen #JUnit5 #springio19
JUnit 4 @Ignore and Assumption Support
(5.4)
• @EnableJUnit4MigrationSupport
o registers the IgnoreCondition
o supports @Ignore analogous to @Disabled
o includes @EnableRuleMigrationSupport semantics
• JUnit Jupiter supports JUnit 4 assumptions
o methods in org.junit.Assume
o AssumptionViolatedException
52. 52@sam_brannen #JUnit5 #springio19
New Features since 5.0
• JUnit Maven BOM
• Parallel test execution
• Output capture for System.out and System.err
• Tag expression language
• Custom test sources for dynamic tests
• Improved Kotlin support
• Numerous enhancements for parameterized tests
• Built-in @Enable* / @Disable* conditions
• @RegisterExtension
• TestInstanceFactory
• …
53. 53@sam_brannen #JUnit5 #springio19
New Features since 5.4
• New junit-jupiter dependency aggregating artifact
• XML report generating listener
• Test Kit for testing engines and extensions
• null and empty argument sources for @ParameterizedTest methods
• @TempDir support for temporary directories
• DisplayNameGenerator SPI
• TestWatcher extension API
• Ordering for @Test methods and @RegisterExtension fields
• Improved JUnit 4 migration support for assumptions and @Ignore
• …
55. 55@sam_brannen #JUnit5 #springio19
Coming in JUnit 5.5
• Boolean values in @ValueSource
• Repeatable annotations for built-in conditions
• Declarative, preemptive timeouts for tests in JUnit Jupiter
• New InvocationInterceptor extension API
• execution in a user-defined thread
• Configurable test discovery implementation for test engines
• …
56. 56@sam_brannen #JUnit5 #springio19
The 5.x Backlog
• Custom ClassLoader
• Programmatic extension management
• Declarative and programmatic test suites for the JUnit Platform
• Parameterized test classes
• Scenario tests
• New XML / JSON reporting format
• …
58. 58@sam_brannen #JUnit5 #springio19
Spring Support for JUnit Jupiter
• Fully integrated in Spring Framework 5.0!
• Supports all Core Spring TestContext Framework features
• Constructor and method injection via @Autowired, @Qualifier, @Value
• Conditional test execution via SpEL expressions
• ApplicationContext configuration annotations
• Also works with Spring Framework 4.3
https://github.com/sbrannen/spring-test-junit5
60. 60@sam_brannen #JUnit5 #springio19
Automatic Test Constructor Autowiring (5.2)
• By default, a test class constructor must be annotated with @Autowired
• The ”default” can be changed
• set spring.test.constructor.autowire=true
• JVM system property or SpringProperties mechanism
• @TestConstructor(autowire = true/false)
• Overrides default on a per-class basis
66. 66@sam_brannen #JUnit5 #springio19
How can I help out?
• Participate on GitHub
• Report issues
• Suggest new features
• Participate in discussions
• Answer questions on Stack Overflow and Gitter
• Support the JUnit Team with donations via Steady HQ
https://steadyhq.com/en/junit
69. 69@sam_brannen #JUnit5 #springio19
Demos Used in this Presentation
https://github.com/sbrannen/junit5-demo
https://github.com/junit-team/junit5/tree/master/documentation/src/test