Issue
I am trying to write junit tests for a class having two overloaded methods. Here is my Code Under Test
public class Solution {
public static String getDurationString(int minute, int seconds) {
if (minute < 0) {
return "Invalid Value";
} else if (seconds < 0 || seconds > 59) {
return "Invalid Value";
} else {
int hours = minute / 60;
minute %= 60;
return getTimeString(hours) + "h " + getTimeString(minute) + "m " + seconds + "s";
}
}
public static String getDurationString(int seconds) {
if (seconds < 0) {
return "Invalid Value";
}
int minutes = seconds / 60;
seconds %= 60;
int hours = minutes / 60;
minutes %= 60;
return getTimeString(hours) + "h " + getTimeString(minutes) + "m " + seconds + "s";
}
//returns value in xx format
private static String getTimeString(int val) {
if (val < 10) {
return "0" + val;
}
return "" + val;
}
}
I am able to test the getDurationString(min,sec) function using some data using JUnit's Parameterized Runner. I want to use same testcode to write test for getDurationString(sec) function, But i am not sure how to do that. I looked at some stackoverflow question but it's not helping(may be because i am using JUnit4).
Any idea how to achieve this with JUnit4?
UPDATE: Added test code for reference
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import static org.junit.Assert.assertEquals;
@RunWith(Parameterized.class)
class SolutionTest {
@Parameterized.Parameters(name = "Test{index} -> {0} min {1} sec returns {2}")
public static Iterable<Object[]> dataForTwoParameterMethod() {
return Arrays.asList(new Object[][]{
{-1, 10, "Invalid Value"}, //minutes < 0 returns "Invalid value"
{1, -1, "Invalid Value"}, //Negative seconds value
{61, 50, "01h 01m 50s"}, //valid value returns time in format "XXh YYm ZZs"
});
}
int minute;
int seconds;
String durationString;
public SolutionTest(int minute, int seconds, String durationString) {
this.minute = minute;
this.seconds = seconds;
this.durationString = durationString;
}
@Test
public void getDurationString() {
assertEquals(durationString, Solution.getDurationString(minute, seconds));
}
@Test @Ignore("TODO: Not able to find a way to inject two different data into one JUnit Test")
public void testGetDurationString() {
//TODO: how to use two data in single data driven test
}
}
Solution
If I understand you right, you have one set of parameters:
{-1, 10, "Invalid Value"}, //minutes < 0 returns "Invalid value"
{1, -1, "Invalid Value"}, //Negative seconds value
{61, 50, "01h 01m 50s"}, //valid value returns time in format "XXh YYm ZZs"
which you use to test the two-argument method getDurationString
. And - this is my understanding - you also want to provide a second set of parameters, maybe
{-1, "Invalid Value"}, //seconds < 0 returns "Invalid value"minutes, "
{0, "00h 00m 00s"}, //boundary case, everything zero
{1, "00h 00m 01s"}, //last digit (seconds)
{10, "00h 00m 10s"}, //but last digit (seconds)
{59, "00h 00m 59s"}, //boundary case
{60, "00h 01m 00s"}, //boundary case, last digit (minutes)
...
to test the one-argument method getDurationString
. However, to do this with JUnit4, you will have to create a second test class - you can not put two different sets of parameters into the same class.
You can have in one class with parameterized tests many test methods - but they will all operate on the same set of parameters, as defined under @Parameterized.Parameters
.
Note that this is different from the way parameterized tests are implemented in JUnit5: In JUnit5 for every individual parameterized test method it can be decided separately what input parameters the test method shall receive. This is done by annotating each test method with the information where the test data comes from: https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests
Answered By - Dirk Herrmann