Sure, you like JUnit. (I mean, who doesn’t?) And you’ve probably heard that JUnit 5 is coming out. But… you’re just not convinced that it’s worth the time to look at it. I mean, not just yet. You’re waiting for it to be released, right?
Well, I say wait no more, and in this post, I’ll give you five reasons you should be using JUnit 5. Like, right now.
Reason #1 – Awesome New Features in JUnit 5
@Nested – this annotation allows you to create nested groups of related test classes within a single test class. This (1) allows your unit tests a more natural style of expression (e.g., Behavior-Driven Testing), (2) nesting enables additional structure that makes testing multiple overloaded methods much easier to write (so long
testMyMethod_StringStringInteger_1()), and (3) lets all of the nested tests share expensive overhead at the class level, while still allowing the Before/After (think
tearDown()) within the nested test.
@Tag – this annotation allows you give tag names to your unit test classes and methods that allow the filtering mechanism to skip a class or test(s) within a class based on these tags (but don’t confuse this with block-level conditional execution provided by Assumptions, which we’ll see next).
Assumptions work with JDK 8 Lambda support to let you write more compact tests. The new
assertAll() method, for example, lets you group assertions, and execute them all of the assertions in a group, and report failures together. Conditional execution of unit tests using
Assumptions is nothing new to JUnit, but the
Assumptions API has been revamped to make it more expressive.
assumingThat() method (part of the
Assumptions class) combines the new, more expressive API with lambda expressions to create unit tests that are easier to read, and test reports that are easier to decipher.
Designed to replace the existing extension poins in JUnit 4 (like
@Rule), the JUnit 5 extension model defines a number of points in the unit test lifecycle (ten at the time of this writing!), and a corresponding interface for each one. You use the JUnit 5 extension model to plug in code (called, you guessed it, extensions) that implements one or more of these interfaces, and when that point in the lifecycle is reached your code is executed. This lets you do things like execute code before and after tests, and even control whether or not tests are run at all.
Test method parameter injection
Unless you were using a third party library with a prior version of JUnit, the standard Runner implementations did not allow test methods to have parameters. That changes with JUnit 5. Through the ParameterResolver interface (corresponding to one of the extension points in the test lifecycle), you can write code to resolve parameters when your tests run.
supports() method, your ParameterResolver decides whether or not the specified parameter is supported by your Extension. If not, the framework marches on, but if so, your
resolve() method handles creating/accessing/coughing up the object instance that is passed in for the parameter. Very cool indeed.
Reason #2 – New Architecture in JUnit 5
Architecture? Zzzzzzz. Who cares? Well, the architecture of JUnit 5 has a clear separation of concerns between how to discover and run tests, and how to write tests. Gone are the days when tool vendors use JUnit internal APIs to function (which, ironincally, limits JUnit’s ability to move forward).
The JUnit 5 architecture is split up into three projects:
- JUnit Jupiter
- JUnit Vintage
- JUnit Platform
The idea is that you as an application developer don’t really need to worry about how JUnit does its thing. But if you do, the same APIs are exposed (no more “internal” APIs used only by tools developers), providing a consistent approach to extending JUnit.
This means better tool support, and a cleaner API, which enables support for multiple versions of JUnit tests.
Reason #3 – Backward Compatibility for JUnit 4
Upgrading to a new major release of software usually means rewriting EVERYTHING, right? Not with JUnit 5; it is totally backward compatible with JUnit 4. In fact, you can run JUnit 4 (and even JUnit 3) unit tests in the same project as JUnit 5 tests. It takes a little work (hey, nothing is free, right?) but your investment in JUnit 3 and 4 is still good.
How does JUnit 5 achieve this? Through the JUnit Vintage test engine, which allows JUnit 4 and JUnit 3 tests to be run. Not only that, but until JUnit 5 native tool support catches up, you should still be able to use your favorite IDE to run JUnit4 tests with the JUnitPlatform class.
I won’t lie to you, there are some features of JUnit 4 that don’t play so well with JUnit 5 (e.g., Rules), but is migration help available in the JUnit 5 user docs.
Reason #4 – Open Test Alliance
Open… what now? To facilitate an open approach to JUnit tool support, the JUnit Lambda team (the code name of JUnit 5) formed a new open source project called the Open Test Alliance for the JVM.
So far, testing frameworks have one button to push if a test fails:
java.lang.AssertionError. Sure, they can all extend that (and do), but each has its own take on it, leading to divergence, and difficulty in integrating those frameworks in with our favorite IDEs. The Open Test Alliance’s framework provides common building blocks for testing frameworks.
Why should you care? Because consistent implementations lead to better tool support. And that’s a cool feature all of us developers can enjoy.
Reason #5 – Choices for your testing framework
As Nicolai Parlog explains it in this post, the entire goal of the JUnit 5 revamp was to allow the success of JUnit to enable the use of other testing frameworks. Because other testing frameworks can build on the JUnit 5 architecture (by providing a test engine), we have a choice of frameworks.
Like TestNG? Spock? Coconut? Or maybe you want to write your own test framework? So long as the framework provides the necessary JUnit 5 architectural components, and your IDE supports JUnit 5, we can use that framework. Let the supreme coolness of that sink in.
Ahhhhhh, there it is…
Learn more about Java programming on developerWorks
- JUnit.org website
- JUnit 5 User Doc
- OTA opentest4j
- JUnit Core Principles