..

JUnit 5 custom extensions

At triply.at, we recently made the big switch from JUnit4 to JUnit5. Besides the main features of conditional test execution, nested unit tests and parameterised tests that made us take this leap of faith, there is another very interesting feature called Jupiter extensions. I’ll dive deeper into that later on. If you don’t want to hear about JUnit5 in general, just skip ahead to the next headline!

The migration from version 4 to 5 of the testing framework surprisingly turned out to be far less of a hassle than we initially expected. A big part of the ease of adapting JUnit5 can be attributed to the new modular setup: the whole project is split up into the platform and platform launcher infrastructure at the bottom and different TestEngines that build on top of them. Through the JUnit Vintage test engine backwards compatibility to JUnit3 and JUnit4 is given, whereas the Jupiter test engine is used to execute tests with the new API.


junit architecture

photo credit: igorski.co

A major drawback in adapting JUnit 5 is that it is only compatible with Java version 8 and above. Since we’re running all of our code on Java8 anyway, that wasn’t a big concern for us at triply.


I always hate the feeling, when a test fails and you have to go look up what was wrong. Especially when you’re working with networked code or running integration tests that depend on other services to respond correctly. So once your test fails, you begin searching for the error, looking at your logs, and so on and so forth. With the newly introduced Test Extensions, it is possible to add additional output to messages, which can be used to add debug scripts you only have to copy to your terminal, links to remote databases, and much more. An extension class for adding output to exceptions can look like this:

package at.triply.backend.test

import org.junit.jupiter.api.extension.ExtensionContext
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler
import java.net.URLEncoder

class TestAdditionalOutputExtension : TestExecutionExceptionHandler {
  override fun handleTestExecutionException(
  context: ExtensionContext?,
    throwable: Throwable
  ){
    println("===================================================\n" +
      "Hey, there seems to be something wrong with your test!\n" +
      throwable.stackTrace.take(5).joinToString("\n")
    )
  throw throwable
  }
}

Last but not least, we still have to register the extension to allow JUnit to use it. For this we have two options: we can either annotate all of our test classes with @ExtendWith(TestAdditionalOutputExtension.class) or enable the extension for all test classes by adding the following two files:

//file:resources/META-INF/services/org.junit.jupiter.api.extension.Extension
at.triply.backend.test.TestAdditionalOutputExtension
#file: junit.platform.properties
junit.jupiter.extensions.autodetection.enabled

This extension only prints a simple message, but in that place you could add some more information like

And that’s’ a wrap! I hope you learned something you didn’t know beforehand! If there’s anything I can help you with, just leave a comment or shoot me an email.