How well do you know your JUnit trivia?

Our long-running trivia series has come to an end. This week, we’re looking at one final subject: JUnit, a popular testing framework for Java.
JUnit 5 was the result of approximately two years of work when it was released last year. Deemed to have “the potential to redefine testing on the JVM”, JUnit 5 consisted of three different modules: JUnit Platform, JUnit Jupiter, and JUnit Vintage. JUnit just released version 5.3 last month, with all kinds of shiny new features and tools for developers.
To get you ready, we worked with Nicolai Parlog of CodeFX to test your knowledge of JUnit.
1. Why was JUnit completely rewritten and published as version 5 instead of improving the existing version and releasing 4.13?
a) JUnit 4’s extension model has deep-rooted problems that could not be fixed by refactoring.
b) Due to some tools’ use of reflection over JUnit 4’s internals (down to private fields), JUnit 4’s evolution was severely hampered.
c) Everybody wanted to finally start coding in Java 8..
d) All of the above.
2. Why is JUnit 5’s default test API called “Jupiter”?
a) Someone really loves Greek gods.
b) Because it was developed for JUnit’s fifth version and Jupiter is the fifth planet.
c) It’s an homage to some song from the early 2000s.
d) It sounded cool.
3. JUnit 5 has a clever architecture, part of which is the split of Jupiter into an API and an engine. You only need to depend on the API to write tests but you should also add the engine as a dependency. Why?
[Hint]
SEE ALSO: JUnit 5.3 arrives with lots of updates in tow
4. How does the JUnit team communicate to users and extension developers which classes and methods they are supposed to use and (more importantly) which to leave alone because they are considered implementation details that can change at any time.
[Hint]
5. Some use cases can be solved with both dynamic tests and parameterized tests, but even though they might look the same in tests reports (e.g. in your IDE’s test runner tab), their interaction with the rest of your test class differs in an important detail – one could say that dynamic tests are inferior in that regard. What’s that details?
[Hint]
6. To write parameterized tests, you need to add a specific artifact org.junit.jupiter : junit-jupiter-params
. Why? After all, this is not necessary for other features like dynamic tests.
7.If you write your own extensions and have to manage its state, you should use the class ExtensionContext.Store
for that instead of fields. Why?
[Hint]
8. The extension context store has three defining characteristics. Name them.
a)
b)
c)
[Hint]
9. How does Jupiter allow extensions to seamlessly blend into its API? (For example, by providing annotations like @IntegrationTest
.) Which property of annotations does it use for that?
[Hint]
10. The Jupiter annotation @DisabledIf
allows you to define a script that will be evaluated and whose result determines whether the annotated test will be disabled or not. By default, the script is presumed to be JavaScript and evaluated within the JVM. That works fine on Java 8 to 11, but may pose a problem in the future. Why?
SEE ALSO: Embracing JUnit 5 with Eclipse
Answers
1. d) All of the above. JUnit 4’s extension model has deep-rooted problems that could not be fixed by refactoring:
- Runners and Rules overlap
- Runners are very powerful, but also complex and exclusive
- Rules are light-weight, but can only interact in limited ways
Due to some tools’ use of reflection over JUnit 4’s internals (down to private fields), JUnit 4’s evolution was severely hampered.
Everybody wanted to finally start coding in Java 8.
2. b) Because it was developed for JUnit’s fifth version and Jupiter is the fifth planet. That it also starts with “Ju” was just a bonus.
3. So that tools like Maven Surefire know exactly which version of the engine they need to run your tests.
4. They apply the @API
annotation. You should only rely on elements that are annotated with @API(STABLE)
or @API(MAINTAINED)
.
5. Dynamic test are not fully integrated into the lifecycle and methods annotated with @BeforeEach
/@AfterEach
are not called for individual tests – only for the @TestFactory
method. For parameterized tests, on the other hand, each execution is framed by before/after methods.
6. One way to parameterize tests is to provide arguments as CSV strings/files, which Jupiter then takes apart. Nobody wants to write a CSV parser, though, so a dependency was added for that. This went against Jupiter’s goal to avoid external dependencies and the only way to resolve that situation was to place @ParameterizedTest
and the code that runs it into its own artifact.
7. Jupiter makes no guarantees about your extension’s lifecycle. Whether an instance is used for a single test, a container, or the entire test suite is not defined and you hence not be sure how long the information in that field survives.
8. Namespaced, hierarchical, and organized as key-value store.
9. Java allows annotating annotations (these are called meta-annotations) and Jupiter is aware of that feature. When scanning for annotations, for example when identifying @Test
-annotated methods, Jupiter will take meta-annotations into account. This way, it also finds @Test
on the custom annotation @ParameterizedTest
and thus registers @ParameterizedTest
-methods as tests.
10. Because Jupiter relies on the Nashorn JavaScript engine that is now deprecated for removal.
SEE ALSO: Big changes to JUnit 5.2
Results
How well did you do?
0-3 correct: You’re starting out around JUnit. Getting to know more about the project could help you out.
4-6 correct: You’re pretty solid in your JUnit trivia, but you still might need to refresh your knowledge.
7-9 correct: Nice! You really know your stuff!
10 correct: You are a JUnit professional.
Programming Pub Quiz: Have you tried our other pub quizzes? Test your knowledge of other topics!
qguge