Jegors Čemisovs
Jegors Čemisovs

Reputation: 740

How to substitute @CsvSourceFile in parent AbstractTest to use different file sources in children tests?

JUnit 5

I have a lot of number properties in separate classes. They all implement Property interface and I would like to test them all. All test looks identical like this:

@DisplayName("Given Jumping property")
class JumpingTest {
    private Property underTest;

    @BeforeEach
    void setUp() {
        underTest = new Jumping();
    }

    @DisplayName("given test() method")
    @ParameterizedTest(name = "when number is \"{0}\" then \"{1}\"")
    @CsvFileSource(resources = "/property/jumping.csv", numLinesToSkip = 1)
    void testProperty(final BigInteger number, final boolean expected) {
        assertEquals(expected, underTest.test(number));
    }
}

The other property and test class for comparing is

@DisplayName("Given Buzz property")
class BuzzTest {
    private Property underTest;

    @BeforeEach
    void setUp() {
        underTest = new Buzz();
    }

    @DisplayName("given test() method")
    @ParameterizedTest(name = "when number is \"{0}\" then \"{1}\"")
    @CsvFileSource(resources = "/property/buzz.csv", numLinesToSkip = 1)
    void testProperty(final BigInteger number, final boolean expected) {
        assertEquals(expected, underTest.test(number));
    }
}

As you can see the class for Property underTest is changed. Other changes are in @CsvSourceFile and in the description of the test class. These strings can be calculated by this.getClass().getSimpleName(). But I do not know how to substitute this strings.

How I can remove the code duplication?

Is it possible to eliminate a duplicate code in JUnit 5?

How to properly do this?

Upvotes: 1

Views: 221

Answers (1)

hohserg
hohserg

Reputation: 452

You can reach it with dynamic tests

https://www.baeldung.com/junit5-dynamic-tests

Something like follow:

List<String> csvList = Arrays.asList("/property/buzz.csv","/property/jumping.csv", ...);

@TestFactory
Stream<DynamicContainer> buzzTest(){
   return 
      csvList.stream()
         .map(resource -> 
            DynamicContainer.dynamicContainer(
               resource, 
               readCSV(resource).stream()
                  .map(pair ->
                     DynamicTest.dynamicTest(
                        String.format("when number is \"%d\" then \"%b\"", pair.getLeft(), pair.getRight()),
                        () -> {
                           BigInteger number = pair.getLeft();
                           boolean expected = pair.getRight();
                           assertEquals(expected, new Buzz().test(number));
                        }
                     )
                  )
            );
}

List<Pair<BigInteger, Boolean>> readCSV(String resource){
   //todo
}

Upvotes: 1

Related Questions