Issue
Let's say I've created a modular project in maven
, which has api
interface defined in myproject-api
, and two implementations of this interface in myproject-impl
and myproject-impl2
.
myproject-api
myproject-impl
myproject-impl2
I want to create a single test suite, that I could run against both implementations. Of course in the future, I could add another implementation and I would also want to test it using these common tests.
What would be the best practice to achieve that kind of shared tests with junit?
Example of the interface (in myproject-api
):
public interface SmallLettersSource {
String read();
}
Implementations:
- in module
myproject-impl
:
class ASource implements SmallLettersSource {
@Override
public String read() {
return "a";
}
}
- in module
myproject-impl2
:
class BSource implements SmallLettersSource {
@Override
public String read() {
return "b";
}
}
And test (I would also want to add it to myproject-api
):
@Test
void test() {
assert(source.read().equals(source.read().toLowerCase()));
}
Solution
I came up with the following solution:
in
myproject-api
I created classCommonTestSuite
, which is returning list ofDynamicTest
objects:public class CommonTestSuite { private final Source source; public CommonTestSuite(Source source) { this.source = source; } public Collection<DynamicTest> tests() { return Arrays.asList( dynamicTest("Should return only lowercase.", this::testLowercase), dynamicTest("Should return only one letter.", this::testLength) ); } void testLowercase() { assert(source.read().equals(source.read().toLowerCase())); } void testLength() { assert(source.read().size() == 1); } }
- Then in tests of my implementation modules, I need only to do:
class MyProjectImplTest { @TestFactory Collection<DynamicTest> test() { return new CommonTestSuite(new ASource()).tests(); } }
and for other modules, I need to do a similar setup. This way I can share common tests between various modules.
Answered By - Krzysztof Atłasik
Answer Checked By - Clifford M. (JavaFixing Volunteer)