2

I've got following code in IAdder.java:

public interface IAdder {

int add(int a, int b);

}

Then the following implementations (one in SimpleAdder.java and another in AbsAdder.java):

public class SimpleAdder implements IAdder {

@Override
public int add(int a, int b) {
    return a+b;
}

}

public class AbsAdder implements IAdder {

@Override
public int add(int a, int b) {
    return Math.abs(a) + Math.abs(b);
}

}

Now I want to test with Junit5 so I start writing the following in SimpleAddertest.java:

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class SimpleAdderTest {

IAdder ia = new SimpleAdder();

@Test
void add() {
    assertEquals(10, ia.add(7, 3));
}

}

To test AbsAdder I could add the following test class AbsAdderTest:

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class AbsAdderTest {

IAdder ia = new AbsAdder();

@Test
void add() {
    assertEquals(10, ia.add(7, 3));
}

}

What's the best way to avoid this code repetition in Junit5? I ve seen other posts on SO but no one answered this simple question in a simple way.

2
  • 2
    What code repitition? They're two different implementations so you need to test both use cases. Similarly you'll need to test add(-5,-7) in both, though with different results. Commented May 21, 2020 at 6:47
  • 1
    I don't think this can be called code repetition as you are testing different implementations. There might be another implementation in future which will not give 7+3=10. Commented May 21, 2020 at 6:50

1 Answer 1

2

You can use a @ParameterizedTest, where you can pass the implementation and the test cases, e.g.

@ParameterizedTest
@MethodSource("sourceMethod")
public void test(IAdder add, int a, int b, int expected) {
    assertEquals(expected, add.add(a, b));
}

public static Stream<Arguments> sourceMethod() {
    final SimpleAdder simpleAdder = new SimpleAdder();
    final AbsAdder absAdder = new AbsAdder();
    return Stream.of(
            Arguments.of(simpleAdder, 2, 3, 5),
            // add more test cases for SimpleAdder, e.g. 
            Arguments.of(simpleAdder, 2, 0, 2),
            Arguments.of(simpleAdder, 0, 4, 4),
            Arguments.of(absAdder, -2, -5, 7),
            // add more test cases for AbsAdder, e.g. 
            Arguments.of(absAdder, -2, 0, 2),
            Arguments.of(absAdder, 0, -9, 9)
    );
}
Sign up to request clarification or add additional context in comments.

8 Comments

don't think assertThat(add.add(a, b), equalTo(expected)); is part of Junit5?
need to change that line to assertEquals(expected, add.add(a, b));
what if I wanted to add MethodSource to all the tests in a class?
@FrancescoDassisis yeah, sorry about that, I was using hamcrest, thanks for the edit! import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.junit.MatcherAssert.*;
You can have as many MethodSources and as many ParameterizedTests as you want. All JUnit cares about is having a static method which returns a Stream of Arguments and the number/type of arguments matching the signature of your parameterized test. Is this what you were asking? Maybe I haven't understood your last question?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.