Practical Guide to JUnit 5 Parameterized Tests

Learn how to write JUnit 5 parameterized tests.

Photo by Green Chameleon on Unsplash

If you have not heard of JUnit 5, you may want to check out the following guides which I find very useful to kickstart the journey with JUnit 5:

Every upgrade might be a chore to everyone, but I personally feel that the advantages that JUnit 5 brings, outweighed the pain and time I used to migrate from JUnit 4 to JUnit 5 (it is quite easy, just laborious 😅).

In my previous article (see below 👇), I have touched on creating a JUnit 5 extension to help in testing Apache Spark easily in your Apache Spark Java project.

In this tutorial, I will be going through how we could leverage JUnit 5 Parameterized Tests to allow us to write a single test to execute with multiple different arguments.

What Do We Need

We will need the following dependencies:

Next, to use parameterized test, we will use @ParameterizedTest annotation instead of @Test annotation.

Now, we are ready to start to learn the different ways to provide arguments to the test. According to the documentation, there are a total of 10 annotation types that we could use:

  • ArgumentsSource
  • ArgumentsSources
  • CsvFileSource
  • CsvSource
  • EmptySource
  • EnumSource
  • MethodSource
  • NullAndEmptySource
  • NullSource
  • ValueSource

1. @ValueSource

To test with a single argument from the value source. The supported types include shorts(), bytes(), ints(), longs(), floats(), doubles(), chars(), booleans(), strings(), and classes().

Example: If the argument to test is an integer

Example: If the argument to test is a string

Note: You may notice that we are unable to set stringToTest to null. The workaround is to use @MethodSource or @ArgumentSource.

2. @MethodSource

To test with a single argument from the values returned from factory methods of the class in which this annotation is declared or from static factory methods in external classes referenced by fully qualified method name.

3. @ArguementsSource

To test with a single argument with values provided by an argument provider. This method allows us to reuse it for multiple other test classes (#DRY).

4. @ArgumentsSources

To test with a single argument with values provided by multiple argument providers. @ArgumentsSources is a simple container for one or more ArgumentsSource annotations.

Note, however, that the use of the @ArgumentsSources container is completely optional since @ArgumentsSource is a repeatable annotation.

So you could either do this

or

5. @EmptySource

To test with a single empty argument. You may also know from the documentation, @EmptySource, is an ArgumentsSource. Therefore, we could use this to test for an empty argument instead of writing our own for the following types below. Subtypes of the supported types are not supported.

  • String
  • List
  • Set
  • Map
  • primitive arrays — for example int[], char[][], etc
  • object arrays — or example String[], Integer[][], etc

6. @NullSource

To test with a single null argument. Similar to @EmptySource, @NullSource is also an ArgumentsSource.

Note that @NullSource cannot be used for an argument that has a primitive type.

7. @NullAndEmptySource

To test with a single null and empty argument. This is equivalent to annotating the method with @NullSource and @EmptySource.

So you could either do this to test for both null and empty argument

or

8. @EnumSource

To test with a single enum argument. @EnumSource is an ArgumentsSource for constants of an Enum.

To include only certain enum values of an Enum class during the test, we could do the following

To exclude certain enum values of an Enum class during the test, we could do the following

9. @CsvSource

To test with multiple arguments. @CsvSource is an ArgumentsSource that reads comma-separated values (CSV) from one or more supplied CSV lines.

There are a few options that we could use to customize for CsvSource: emptyValue (default: “”), nullValues, and delimiter (default: ‘,’).

10. @CsvFileSource

To test with multiple arguments. This is similar to @CsvSource but the CSV values are loaded from one or more classpath resources or CsvFileSource.files().

There are a few options that we could use to customize for CsvFileSource: lineSeparator (default: “\n”), delimiter (default: ‘,’), numLinesToSkip (default: 0), emptyValue (default: “”) and nullValues.

And there we have it. I hope you have found this useful. Thank you for reading. If you enjoyed this article, remember to follow me for more updates!

Stay tuned for more articles ✌️.

If you are not a Medium member yet and want to become one, click here.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Wei Kang

Wei Kang

Once a programmer, always a programmer