26

I've googled for JUnit test case, and it comes up with something that looks a lot more complicated to implement - where you have to create a new class that extends test case which you then call:

public class MathTest extends TestCase {
    protected double fValue1;
    protected double fValue2;

    protected void setUp() {
       fValue1= 2.0;
       fValue2= 3.0;
    }
 }

public void testAdd() {
   double result= fValue1 + fValue2;
   assertTrue(result == 5.0);
}

but what I want is something really simple, like the NUnit test cases

[TestCase(1,2)]
[TestCase(3,4)]
public void testAdd(int fValue1, int fValue2)
{
    double result= fValue1 + fValue2;
    assertIsTrue(result == 5.0);
}

Is there any way to do this in JUnit?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Steph
  • 261
  • 3
  • 3
  • 2
    JUnit has two styles: version 3, which you have in your example, and version 4, which uses annotations. Do you really want to know about version 3? – Raedwald Dec 29 '10 at 12:41
  • Ah.. No...I want to know about 4.5... – Steph Dec 29 '10 at 13:51
  • 1
    I think what I might be looking for is Parameterised Tests. But even this looks a bit verbose and a little bit random... http://www.mkyong.com/unittest/junit-4-tutorial-6-parameterized-test/ – Steph Dec 29 '10 at 13:53
  • 2
    looks like you can only have 1 parameterised test per class. Shit or what? – Steph Dec 29 '10 at 13:56
  • you can use http://kentbeck.github.com/junit/javadoc/latest/org/junit/experimental/runners/Enclosed.html to put multiple test classes in one class, which would allow you to have multiple parameterized tests per class. – NamshubWriter Jan 02 '11 at 15:06
  • @Steph You can have multiple test methods that take the same parameters. If you want another set of parameters, you do need a new test class. – Jeanne Boyarsky Jan 23 '11 at 18:24
  • 2
    NUnit is derived from JUnit and now it is much advanced than JUnit. TestCase is just one of the example that makes NUnit so easy to use. – Kenneth Xu Jun 03 '12 at 21:40
  • Uhhh, I answered this question 3 years ago, but just now noticed that 1 + 2 != 5, nor does 3 + 4 – Gonen I Nov 05 '16 at 21:43

6 Answers6

13

2017 update: JUnit 5 will include parameterized tests through the junit-jupiter-params extension. Some examples from the documentation:

Single parameter of primitive types (@ValueSource):

@ParameterizedTest
@ValueSource(strings = { "Hello", "World" })
void testWithStringParameter(String argument) {
    assertNotNull(argument);
}

Comma-separated values (@CsvSource) allows specifying multiple parameters similar to JUnitParams below:

@ParameterizedTest
@CsvSource({ "foo, 1", "bar, 2", "'baz, qux', 3" })
void testWithCsvSource(String first, int second) {
    assertNotNull(first);
    assertNotEquals(0, second);
}

Other source annotations include @EnumSource, @MethodSource, @ArgumentsSource and @CsvFileSource, see the documentation for details.


Original answer:

JUnitParams (https://github.com/Pragmatists/JUnitParams) seems like a decent alternative. It allows you to specify test parameters as strings, like this:

@RunWith(JUnitParamsRunner.class)
public class MyTestSuite {
    @Test
    @Parameters({"1,2", "3,4"})
    public testAdd(int fValue1, int fValue2) {
       ...
    }
}

You can also specify parameters through separate methods, classes or files, consult the JUnitParamsRunner api docs for details.

Soulman
  • 2,910
  • 24
  • 21
11

Apparently the correct answer is "No, there is no equivalent." And that's sad.

JUnit parameterized tests and theories (as mentioned here and in JUnit - How to test a method with different values?) both can get the job done, but nowhere nearly as cleanly. They are sadly complicated to write, and hard to read.

I hope that one day JUnit can add an easier, NUnit-like syntax. Seems like it shouldn't be that difficult; though perhaps lambdas are needed?

Community
  • 1
  • 1
Allan
  • 1,063
  • 10
  • 18
  • Lambdas are probably not needed as much as proper generics, but that's only a guess here. Annotations/Attributes don't depend on anonymous functions at all. – Joey Sep 10 '13 at 06:50
6

It might also be worthwhile to check out JUnit Theories and Datapoints. They let you parametrize tests, but run an all-pairs type combination on your inputs.

hyde
  • 60,639
  • 21
  • 115
  • 176
Gonen I
  • 5,576
  • 1
  • 29
  • 60
5

You can have junit with parameters using zohhak

Usage example:

@RunWith(ZohhakRunner.class)
public class HelloWorldTest {

    @TestWith({
        "2, 1,   3",
        "3, 5,   8"
    })
    public void should_add_numbers(int addend1, int addend2, int result) {

        assertThat(addend1 + addend2).isEqualTo(result);
    }
}
piotrek
  • 13,982
  • 13
  • 79
  • 165
Denis Bakharev
  • 959
  • 1
  • 9
  • 7
2

It's silly but here is the workaround that I have in the end. Use 4 lines instead one line.

@Test
public void testAdd1() {
    testAdd(1,2);
}
@Test
public void testAdd2() {
    testAdd(3,4);
}
private void testAdd(int fValue1, int fValue2)
{
    double result= fValue1 + fValue2;
    assertIsTrue(result == 5.0);
}
Kenneth Xu
  • 1,514
  • 15
  • 15
  • I like ur workaround. Today we are supposed to use [@ParameterizedTest](https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests) annotation – rupweb Feb 18 '21 at 11:42
0

I have used a holding class to hold my test cases like this:

class FlexiTest {
String var1;
String var2;
double var3;
String var4;
MyObject var5;
double expected;

public FlexiTest(String var1, String var2, double var3, String var4, MyObject var5, double expected) {
    super();
    this.var1;
    this.var2;
    this.var3;
    this.var4;
    this.var5;
    this.expected = expected;
}

Then setup a stream of my the test class objects like this:

static Stream<FlexiTest> provider(){

    FlexiTest ft1 = new FlexiTest("1", "2", 3, "4", MyObject.A, 1.1);
    FlexiTest ft2 = new FlexiTest("10", "20", 30, "40", MyObject.B, 11);
    FlexiTest ft3 = new FlexiTest("100", "200", 300, "400", MyObject.C, 110);
    
    return Stream.of(ft1, ft2, ft3);
}

Then annotated the Test method with @ParameterizedTest and @MethodSource with the stream of objects method name. Also null and empty checks:

@ParameterizedTest
@MethodSource("provider")   
@NullSource
@EmptySource
public void ClientTest(FlexiTest ft)
{
... my test code ...
}
rupweb
  • 3,052
  • 1
  • 30
  • 57