This blog post describes how we can write parameterized tests with JUnit 5. After we have finished this blog post, we:
- Can get the required dependencies with Maven and Gradle.
- Know how we can customize the display name of each method invocation.
- Understand how we can use different argument sources.
- Can write custom argument converters.
Let's start by getting the required dependencies.
Getting the Required Dependencies
Before we can write parameterized tests with JUnit 5, we have to ensure that the junit-jupiter-params
dependency is found from the classpath. If we are using the junit-jupiter
aggregator artifact, we don't have to do anything because all the required dependencies are already added to the classpath. On the other hand, if we aren't using the junit-jupiter
aggregator artifact, we have to make some changes to our build script.
If we are using Maven, we have to add the junit-jupiter-params
dependency to the test
scope. We can do this by adding the following snippet to dependencies
section of our POM file:
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <version>5.8.2</version> <scope>test</scope> </dependency>
If we are using Gradle, we have to add the junit-jupiter-params
dependency to the testImplementation
dependency configuration. We can do this by adding the following snippet to our build.gradle file:
testImplementation( 'org.junit.jupiter:junit-jupiter-params:5.8.2' )
Let’s move on and write our first parameterized test with JUnit 5.
Writing Our First Parameterized Tests
If our test method takes only one method parameter that's either a String
or a primitive type supported by the @ValueSource
annotation (byte
, char
, double
, float
, int
, long
, or short
), we can write a parameterized test with JUnit 5 by following these steps:
- Add a new test method to our test class and ensure that this method takes a
String
object as a method parameter. - Configure the display name of the test method.
- Annotate the test method with the
@ParameterizedTest
annotation. This annotation identifies parameterized test methods. - Provide the method parameters which are passed to our test method. Because our test method takes one
String
object as a method parameter, we can provide its method parameters by annotating our test method with the@ValueSource
annotation.
After we have added a new parameterized test to our test class, its source code looks as follows:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import static org.junit.jupiter.api.Assertions.assertNotNull; @DisplayName("Pass the method parameters provided by the @ValueSource annotation") class ValueSourceExampleTest { @DisplayName("Should pass a non-null message to our test method") @ParameterizedTest @ValueSource(strings = {"Hello", "World"}) void shouldPassNonNullMessageAsMethodParameter(String message) { assertNotNull(message); } }
When we run our parameterized test, we should see an output that looks as follows:
Pass the method parameters provided by the @ValueSource annotation |_ Should pass a non-null message to our test method |_ [1] Hello |_ [2] World
Even though this output looks quite clean, sometimes we want to provide our own display name for each method invocation. Let's find out how we can do it.
Customizing the Display Name of Each Method Invocation
We can customize the display name of each method invocation by setting the value of the @ParameterizedTest
annotation's name
attribute. This attribute supports the following placeholders:
{displayName}
: The display name of the test method.{index}
: The index of the current invocation. Note that the index of the first invocation is one.{arguments}
: A comma separated list that contains all arguments passed to the test method.{argumentsWithNames}
: A comma separated list that contains all arguments (including the name of the method parameter) passed to the test method.{i}
: The actual method parameter (i
specifies the index of the method parameter). Note that the index of the first method parameter is zero.
Let's provide a custom display name to our test method. This display name must display the index of the current invocation and the provided method parameter. After we have configured the custom display name of each method invocation, the source code of our test class looks as follows:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import static org.junit.jupiter.api.Assertions.assertNotNull; @DisplayName("Pass the method parameters provided by the @ValueSource annotation") class ValueSourceExampleTest { @DisplayName("Should pass a non-null message to our test method") @ParameterizedTest(name = "{index} => message=''{0}''") @ValueSource(strings = {"Hello", "World"}) void shouldPassNonNullMessageAsMethodParameter(String message) { assertNotNull(message); } }
When we run our parameterized test, we should see an output that looks as follows:
Pass the method parameters provided by the @ValueSource annotation |_ Should pass a non-null message to our test method |_ 1 => message='Hello' |_ 2 => message='World'
As we remember, the @ValueSource
annotation is a good choice if our test method takes only one method parameter that's supported by the @ValueSource
annotation. However, most of the time this is not the case. Next, we will find out how we can solve this problem by using different argument sources.
Using Argument Sources
The @ValueSource
annotation is the simplest argument source that's supported by JUnit 5. However, JUnit 5 support other argument sources as well. All supported argument sources are configured by using annotations found from the org.junit.jupiter.params.provider
package.
This section describes how we can use the more complex argument sources provided by JUnit 5. Let's start by finding out how we can pass enum
values to our parameterized test.
Passing Enum Values to Our Parameterized Test
If our parameterized test takes one enum
value as a method parameter, we have to annotate our test method with the @EnumSource
annotation and specify the enum values which are passed to our test method.
Let's assume that we have to write a parameterized test that takes a value of the Pet
enum
as a method parameter. The source code of the Pet
enum looks as follows:
enum Pet { CAT, DOG; }
If we want to pass all enum
values to our test method, we have to annotate our test method with the @EnumSource
annotation and specify the enum
whose values are passed to our test method. After we have done this, the source code of our test class looks as follows:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import static org.junit.jupiter.api.Assertions.assertNotNull; @DisplayName("Pass enum values to our test method") class EnumSourceExampleTest { @DisplayName("Should pass non-null enum values as method parameters") @ParameterizedTest(name = "{index} => pet=''{0}''") @EnumSource(Pet.class) void shouldPassNonNullEnumValuesAsMethodParameter(Pet pet) { assertNotNull(pet); } }
When we run this test method, we see that JUnit 5 passes all values of the Pet
enum
to our test method:
Pass enum values to our test method |_ Should pass non-null enum values as method parameters |_ 1 => pet='CAT' |_ 2 => pet='DOG'
If we want to specify the enum
values that are passed to our test method, we can specify the enum
values by setting the value of the @EnumSource
annotation's names
attribute. Let's ensure that the value: Pet.CAT
is passed to our test method.
After we have specified the used enum value, the source code of our test class looks as follows:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import static org.junit.jupiter.api.Assertions.assertNotNull; @DisplayName("Pass enum values to our test method") class EnumSourceExampleTest { @DisplayName("Should pass only the specified enum value as a method parameter") @ParameterizedTest(name = "{index} => pet=''{0}''") @EnumSource(value = Pet.class, names = {"CAT"}) void shouldPassNonNullEnumValueAsMethodParameter(Pet pet) { assertNotNull(pet); } }
When we run this test method, we see that JUnit 5 passes only the value: Pet.CAT
to our test method:
Pass enum values to our test method |_ Should pass non-null enum values as method parameters |_ 1 => pet='CAT'
@EnumSource
annotation provides quite versatile support for filtering enum
values. If you want to get more information about this, you should take a look at the following documents:
Additional Reading:
We have now learned how we can use two different argument sources that allow us to pass one method parameter to our test method. However, most of the time we want to pass multiple method parameters to our parameterized test. Next, we will find out how we can solve this problem by using the CSV format.
Creating Our Test Data by Using the CSV Format
If we have to pass multiple arguments to the invoked test method and the provided test data is used by only one test method (or a few test methods), we can configure our test data by using the @CsvSource
annotation. When we add this annotation to a test method, we have to configure the test data by using an array of String
objects. When we specify our test data, we have to follow these rules:
- One
String
object must contain all arguments of one method invocation. - The different argument values must be separated with a comma.
- The argument values found from each line must use the same order as the method parameters of our test method.
Let's configure the arguments which are passed to the sum()
method. This method takes three method parameters: the first two method parameters contain two int
values and the third method parameter specifies the expected sum of the provided int
values.
After we have configured the test data of our parameterized test, the source code of our test class looks as follows:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import static org.junit.jupiter.api.Assertions.assertEquals; @DisplayName("Should pass the method parameters provided by the @CsvSource annotation") class CsvSourceExampleTest { @DisplayName("Should calculate the correct sum") @ParameterizedTest(name = "{index} => a={0}, b={1}, sum={2}") @CsvSource({ "1, 1, 2", "2, 3, 5" }) void sum(int a, int b, int sum) { assertEquals(sum, a + b); } }
Even though this looks quite clean, sometimes we have so much test data that it doesn't make sense to add it to our test class because our test class would become unreadable. Let's find out how we can load the test data that's passed to the sum()
method from a CSV file.
Loading Our Test Data From a CSV File
We can load our test data from a CSV file by following these steps:
First, we have to create a CSV file that contains our test data and put this file to the classpath. When we add our test data to the created CSV file, we have to follow these rules:
- One line must contain all arguments of one method invocation.
- The different argument values must be separated with a comma.
- The argument values found from each line must use the same order as the method parameters of our test method.
The test-data.csv file configures the test data that is passed to the sum()
method. This file is found from the src/test/resources directory, and its content looks as follows:
1,1,2 2,3,5 3,5,8
Second, we have to annotate our test method with the @CsvFileSource
annotation and configure the location of our CSV file. After we have done this, the source code of our test class looks as follows:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvFileSource; import static org.junit.jupiter.api.Assertions.assertEquals; @DisplayName("Should pass the method parameters provided by the test-data.csv file") class CsvFileSourceExampleTest { @DisplayName("Should calculate the correct sum") @ParameterizedTest(name = "{index} => a={0}, b={1}, sum={2}") @CsvFileSource(resources = "/test-data.csv") void sum(int a, int b, int sum) { assertEquals(sum, a + b); } }
We can now pass multiple method parameters to our parameterized test. However, the catch is that the method parameters of our parameterized tests must be supported by the DefaultArgumentConverter
class. Its Javadoc states that:
The DefaultArgumentConverter is able to convert from strings to a number of primitive types and their corresponding wrapper types (Byte, Short, Integer, Long, Float, and Double), date and time types from the java.time package, and some additional common Java types such as File, BigDecimal, BigInteger, Currency, Locale, URI, URL, UUID, etc.
Next, we will find out how we can solve this problem by using a factory method and a custom ArgumentsProvider
.
Creating Our Test Data by Using a Factory Method
If all parameterized tests which use the created test data are found from the same test class and the logic that creates the test data isn't "too complex", we should create our test data by using a factory method.
If we want to use this approach, we have to add a static
factory method to our test class and implement this method by following these rules:
- The factory method must not take any method parameters.
- The factory method must return a
Stream
,Iterable
,Iterator
, or an array ofArguments
objects. The object returned by our factory method contains the arguments of all test method invocations. - An
Arguments
object must contain all arguments of a single test method invocation. - We can create a new
Arguments
object by invoking thestatic of()
method of theArguments
interface. The arguments provided to theof()
method are passed to our test method when it's invoked by JUnit 5. That's why the provided arguments must use the same order as the method parameters of our test method.
- The factory method must be
static
only if we use the default lifecycle configuration. - The factory method can also return a
Stream
that contain primitive types. This blog post doesn't use this approach because I wanted to demonstrate how we can pass "complex" objects to our parameterized tests.
Let's demonstrate these rules by implementing a factory method that creates the test data which is passed to the sum()
method (we have already used this method in the previous examples). After we have implemented this factory method, the source code of our test class looks as follows:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; @DisplayName("Should pass the method parameters provided by the sumProvider() method") class MethodSourceExampleTest { @DisplayName("Should calculate the correct sum") @ParameterizedTest(name = "{index} => a={0}, b={1}, sum={2}") void sum(int a, int b, int sum) { assertEquals(sum, a + b); } private static Stream<Arguments> sumProvider() { return Stream.of( Arguments.of(1, 1, 2), Arguments.of(2, 3, 5) ); } }
After we have implemented this method, we must ensure that its return value is used when JUnit 5 runs our parameterized test method. We can do this by following these steps:
- Annotate our test method with the
@MethodSource
annotation. - Configure the name of the factory method which creates our test data.
After we have made the required changes to our test class, its source code looks as follows:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; @DisplayName("Should pass the method parameters provided by the sumProvider() method") class MethodSourceExampleTest { @DisplayName("Should calculate the correct sum") @ParameterizedTest(name = "{index} => a={0}, b={1}, sum={2}") @MethodSource("sumProvider") void sum(int a, int b, int sum) { assertEquals(sum, a + b); } private static Stream<Arguments> sumProvider() { return Stream.of( Arguments.of(1, 1, 2), Arguments.of(2, 3, 5) ); } }
This approach works relatively well as long as the factory method is simple and all test methods which use the factory method are found from the same test class. If either of these conditions is false
, we have to implement a custom ArgumentsProvider
.
Creating Our Test Data by Using a Custom ArgumentsProvider
If the test methods which use our test data are found from different test classes or the logic which creates the required test data is so complex that we don't want to add it to our test class, we have to create a custom ArgumentsProvider
.
We can do this by creating class that implements the ArgumentsProvider
interface. After we have created this class, we have to implement the provideArguments()
method that returns a Stream
of Arguments
objects. When we create the returned Stream
object, we must follow these rules:
- The returned object must contain the arguments of all test method invocations.
- An
Arguments
object must contain all arguments of a single test method invocation. - We can create a new
Arguments
object by invoking thestatic of()
method of theArguments
interface. The arguments provided to theof()
method are passed to our test method when it's invoked by JUnit 5. That's why the provided arguments must use the same order as the method parameters of our test method.
Let's create a custom ArgumentsProvider
which provides the test data that's passed to the sum()
method. We can do this by following these steps:
First, we have write a custom ArgumentsProvider
class which returns the test data that's passed to the sum()
method.
After we have created a custom ArgumentsProvider
class, the source code of our test class looks as follows:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ArgumentsProvider; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; @DisplayName("Should pass the method parameters provided by the CustomArgumentProvider class") class ArgumentsSourceExampleTest { @DisplayName("Should calculate the correct sum") @ParameterizedTest(name = "{index} => a={0}, b={1}, sum={2}") void sum(int a, int b, int sum) { assertEquals(sum, a + b); } static class CustomArgumentProvider implements ArgumentsProvider { @Override public Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception { return Stream.of( Arguments.of(1, 1, 2), Arguments.of(2, 3, 5) ); } } }
Second, we have to configure the used ArgumentsProvider
by annotating our test method with the @ArgumentsSource
annotation. After we have done this, the source code of our test class looks as follows:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ArgumentsProvider; import org.junit.jupiter.params.provider.ArgumentsSource; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; @DisplayName("Should pass the method parameters provided by the CustomArgumentProvider class") class ArgumentsSourceExampleTest { @DisplayName("Should calculate the correct sum") @ParameterizedTest(name = "{index} => a={0}, b={1}, sum={2}") @ArgumentsSource(CustomArgumentProvider.class) void sum(int a, int b, int sum) { assertEquals(sum, a + b); } static class CustomArgumentProvider implements ArgumentsProvider { @Override public Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception { return Stream.of( Arguments.of(1, 1, 2), Arguments.of(2, 3, 5) ); } } }
We can now create our test data by using factory methods and custom ArgumentsProvider
classes. However, even though these methods allow us to ignore the limitations of the DefaultArgumentConverter
class, sometimes we want to provide our test data by using strings because this helps us to write tests which are easier to read than tests which use factory methods or custom ArgumentsProvider
classes.
Next, we will find out how we can solve this problem by using a custom ArgumentConverter
.
Using a Custom ArgumentConverter
An ArgumentConverter
has only one responsibility: it converts the source object into an instance of another type. If the conversion fails, it must throw an ArgumentConversionException
.
Let's create an ArgumentConverter
that can convert a String
object into a Message
object. The Message
class is a simple wrapper class that simply wraps the message given as a constructor argument. Its source code looks as follows:
final class Message { private final String message; Message(String message) { this.message = message; } String getMessage() { return message; } }
We can create our custom ArgumentConverter
by following these steps:
First, we have to create a class called MessageConverter
that implements the ArgumentConverter
interface. After we have created this class, its source code looks as follows:
import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.converter.ArgumentConversionException; import org.junit.jupiter.params.converter.ArgumentConverter; final class MessageConverter implements ArgumentConverter { @Override public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { } }
Second, we have to implement the convert()
method by following these steps:
- Throw a new
ArgumentConversionException
if the source object isn't valid. The source object must be aString
that's notnull
or empty. - Create a new
Message
object and return the created object.
After we have implemented the convert()
method, the source code of the MessageConverter
class looks as follows:
import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.converter.ArgumentConversionException; import org.junit.jupiter.params.converter.ArgumentConverter; final class MessageConverter implements ArgumentConverter { @Override public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { checkSource(source); String sourceString = (String) source; return new Message(sourceString); } private void checkSource(Object source) { if (source == null) { throw new ArgumentConversionException("Cannot convert null source object"); } if (!source.getClass().equals(String.class)) { throw new ArgumentConversionException( "Cannot convert source object because it's not a string" ); } String sourceString = (String) source; if (sourceString.trim().isEmpty()) { throw new ArgumentConversionException( "Cannot convert an empty source string" ); } } }
After we have created our custom ArgumentConverter
, we have to create a parameterized test which uses our custom ArgumentConverter
. We can create this test by following these steps:
First, we have to create a new parameterized test method by following these steps:
- Add a new parameterized test method to our test class and ensure that the method takes two
Message
objects as method parameters. - Annotate the test method with the
@CsvSource
annotation and configure the test data by using the CSV format. - Verify that the
Message
objects given as method parameters contain the same message.
After we have created our test method, the source code of our test class looks as follows:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import static org.junit.jupiter.api.Assertions.assertEquals; @DisplayName("Pass converted Message objects to our test method") class MessageConverterExampleTest { @DisplayName("Should pass same messages as method parameters") @ParameterizedTest(name = "{index} => actual={0}, expected={1}") @CsvSource({ "Hello, Hello", "Hi, Hi", }) void shouldPassMessages(Message actual, Message expected) { assertEquals(expected.getMessage(), actual.getMessage()); } }
Second, we have to configure the ArgumentConverter
that creates the arguments passed to our test method. We can do this by annotating the method parameters with the @ConvertWith
annotation. When we do this, we have to configure the used ArgumentConverter
by setting the value of the @ConvertWith
annotation's value
attribute.
After we have configured the used ArgumentConverter
, the source code of our test class looks as follows:
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.converter.ConvertWith; import org.junit.jupiter.params.provider.CsvSource; import static org.junit.jupiter.api.Assertions.assertEquals; @DisplayName("Pass converted Message objects to our test method") class MessageConverterExampleTest { @DisplayName("Should pass same messages as method parameters") @ParameterizedTest(name = "{index} => actual={0}, expected={1}") @CsvSource({ "Hello, Hello", "Hi, Hi", }) void shouldPassMessages(@ConvertWith(MessageConverter.class) Message actual, @ConvertWith(MessageConverter.class) Message expected) { assertEquals(expected.getMessage(), actual.getMessage()); } }
We can now write parameterized tests with JUnit 5. Let's summarize what we learned from this blog post.
Summary
This blog post has taught us seven things:
- Before we can write parameterized tests with JUnit 5, we have to ensure that the
junit-jupiter-params
dependency is found from the classpath. - We have to annotate our parameterized test method with the
@ParameterizedTest
annotation. - We can customize the display name of each method invocation by setting the value of the
@ParameterizedTest
annotation'sname
attribute. - When we configure our test data, our test data must use the same order as the method parameters of our test method.
- If we want pass "complex" objects to parameterized tests which are found from the same test class and the logic that creates these arguments isn't “too complex”, we should create these arguments by using a factory method.
- If the test methods which use our test data are found from different test classes or the logic which creates the required test data is so complex that we don’t want to add it to our test class, we have to create a custom
ArgumentsProvider
. - If we want to provide our test data by using strings and use method parameters which aren't supported by the default argument converters, we have to implement a custom
ArgumentConverter
.
P.S. You can get the example application of this blog post from Github.
Hi Petri
Thanks by this valuable tutorial.
I have the following in JUnit 4, what is your best recommendation about if is necessary to adapt it to JUnit 5 (perhaps is not necessary)
From above some points:
@Parameters
data()
method must have no parameters.data()
method.Something interesting in your tutorial that perhaps should be highlighted, the are no
@Test
methods.Thanks
-Manuel
Hi Manuel,
I think that migrating your existing tests to use JUnit 5 is not a good idea unless:
The thing is that changing your existing code is basically an investment and you want to ensure that you get a good return on your investment. The "problem" is that it's very hard to get even a decent ROI if your existing tests don't have any problems AND the conditions I mentioned earlier are false.
In other words, I guess the answer to your question is: it depends, but most of the time you shouldn't do it.
Hi Petri,
Thank you for the documentation. Its quite elaborate.
I am migrating all my tests from junit 4 to 5.
I am writing a @ParameterizedTest with @MethodSource as input parameters provider.
But the @MethodSource factory method I use has to get parameters from different methods as per the current tests that I have.
Example:
These values are throwing nullpointer exceptions and as per your documentation about the @MethodSource factory method 'A factory method must not take any method parameters'. Can you please let me know if the above functionality can be achieved any way using any other argument sources provided by @ParameterizedTest in junit 5
Hi,
can you let me know what your use case is? It's clear that you want to pass domain, email address, and password to your parameterized test method, but I am not sure how do you specify your test data. For example, do you want to read it from an external source (such as a file or a database) or do you want use a "constant dataset" (a set of constant values)?
Thank you for replying.
I want the test data from few base pages. Like I have a loginPage for all the login related data . In the above example I got the domain, email and password from the base registrationPage. This data from the loginPage or registrationPage or a different page will go into the @MethodSource as argument parameters and from the @MethodSource to the ParameterizedTest.
I have a RegistrationPage in which I have the getFullDomain()
This BasePage below has the RegistrationPage object created and @Autowired so I can access the RegistrationPage getFullDomain() method using the BasePage
My ParameterizedTest Class below is extending the BasePage so I can use the methods in registrationPage without creating an instance for the class separately in the test below.
When I do this and access the getFullDomain() method in my @MethodSource it returns null. And your document on the @MethodSource above says we can't pass external parameters into the @MethodSource. Just wondering if we have any solution for it.
Thank you.
Hi,
I noticed two things:
RegistrationPage
bean into theBasePage
bean by using field injection. However, theBasePage
class isn't annotated with a bean annotation. Also, your test class doesn't load the Spring application context. If you use this configuration, the value of theregistrationPage
field isnull
when you run your test.registrationInputParameters()
must bestatic
.how can we pass string formatted using String.format() as value
I want to do for the json file similar to display in above examples for csv, but in my case I do have multiple json having different keys in each json. I want to extract single key example: key1 from each json and display that key value to parameterisedTest annotation dynamically.
@ParameterizedTest
@JsonFileSource(resource="file1.json")
public void sampleTestMethod(JsonObject obj){
}
}
inside file1.json , I do have multiple jsons and I want to extract key1 from each json and display that key value to the @ParameterizedTest dynamically to show test case name at run time with that value.(key1 holding test case name)
Hi,
First, I am sorry that it took me a long time to answer to your question. I just get so many comments nowadays that sometimes I miss one or two.
Second, unfortunately I don't know how you can fulfill your requirement. I hope that you managed to find an answer to your problem though.
Hi,
You can use this dependency:
http://www.joshka.net/junit-json-params/
Regards!
Everson Mauda (www.mauda.com.br)
Hello Petri
I am so glad I found your tutorial, and really appreciate the references to the documentation. You also covered various ways of Parameterized testing with enough detail and explanation that I can follow. Thank you. I have a question. I want to create and populate a tree with data, and then test methods that use the populated tree to get the answer. In order to do this, I need to create two other object types: Point2D, and RectHv, and I like to be able to create different number of each and different instances for different tests.
So far I have looked into using the @TestInstance(TestInstance.Lifecycle.PER_CLASS) attribute as well as different ParameterizedTesting annotation tags but have not had any success. I am working on the following factory method but have not figured out how to convert the stream I have to one of type . I also get a compiler message saying "the stream is of type void"; my stream that is. The one I created. Here is what I have ...
I am still reading about streams, and need to read the links you provided above. Again, do not know how to thank you for creating this content, and taking the time to provide the links. Before I found your site, I was thinking I wish the articles on Parametrized Testing provided a bit more details and / or covered other supported features. Most were a bit over what I could follow. thank you so much.
I wanted to post an update since I have made progress, but run into an error stating "No ParameterResolver registered for parameter [edu.princeton.cs.algs4.RectHV arg1] in method [void KdTreeTest.range(KdTree,edu.princeton.cs.algs4.RectHV,edu.princeton.cs.algs4.Point2D[])]." I implmented an AgumentProvider as follows:
Hi,
First, I am sorry that it took me some time before I noticed your comment.
The problem is found from the
provideArguments()
method of theKdTreeArgumentsProvider
class.When you invoke the
of()
method of theStream
class, you create a stream which has three elements (kt
,r
, andexpectedPoints
). Also, because you use themap()
method of theStream
class, each element is wrapped inside anArguments
object. In other words, the returned stream contains threeArguments
objects which have one argument per object. Because your parameterized test has three arguments and your provider provides only one, your test fails.You can fix this problem by changing the implementation of the
provideArguments()
method:I hope that this solves your problem.
Hello and thank you so much for the reply. I'll try the solution.