A typical situation within a project is that you created an interface and have a number of implementations. Concluding the former idea the structure of the project follows:
. |-- interface-impl-a | |-- pom.xml | ... |-- interface-impl-b | |-- pom.xml | ... |-- interface-interface | |-- pom.xml | ... |-- interface-test | |-- pom.xml | ... `-- pom.xml
So the question in this case is: How to test the different implementations? But is this true? No. We don't have to test the implementations we have to test the behavior of the interface for all implementations. This can be achieved by writing unit tests in both modules interface-impl-a and interface-impl-b which means in other words to copy&paste the unit test code but this is error prone and of course not effective.
The solution is to implement the unit test code in an abstract class in a separate module interface-test.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public abstract class ImplementationUnitTest { protected static IFunction function; @Test public void firstTest() { assertTrue(function.function( "function1" )); } @Test public void secondTest() { assertFalse(function.function( "function" )); } } |
The more important part is the pom.xml file which is needed in this case. We have to make sure that the test code is made available for other modules as well. So we have to define the pom like the following:
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | < build > < plugins > < plugin > < groupId >org.apache.maven.plugins</ groupId > < artifactId >maven-jar-plugin</ artifactId > < executions > < execution > < goals > < goal >test-jar</ goal > </ goals > </ execution > </ executions > </ plugin > </ plugins > </ build > < dependencies > < dependency > < groupId >${project.groupId}</ groupId > < artifactId >interface-interface</ artifactId > < version >${project.version}</ version > </ dependency > < dependency > < groupId >junit</ groupId > < artifactId >junit</ artifactId > < scope >test</ scope > </ dependency > </ dependencies > |
Based on that we can now implement the unit test for implementation-a like this:
9 10 11 12 13 14 15 16 | public class ImplementationAUnitTest extends ImplementationUnitTest { @BeforeClass public static void beforeClass() { function = new ImplementationA(); } } |
And for implementation-b like this:
9 10 11 12 13 14 15 16 | public class ImplementationBUnitTest extends ImplementationUnitTest { @BeforeClass public static void beforeClass() { function = new ImplementationB(); } } |
The only thing we need to implement is the initialization code to create an instance of the particular class.
|-- interface-impl-a | |-- pom.xml | `-- src | |-- main | | `-- java | | `-- com | | `-- soebes | | `-- maui | | `-- ut | | `-- inter | | `-- ImplementationA.java | `-- test | `-- java | `-- com | `-- soebes | `-- maui | `-- ut | `-- inter | `-- ImplementationAUnitTest.java |-- interface-impl-b | |-- pom.xml | `-- src | |-- main | | `-- java | | `-- com | | `-- soebes | | `-- maui | | `-- ut | | `-- inter | | `-- ImplementationB.java | `-- test | `-- java | `-- com | `-- soebes | `-- maui | `-- ut | `-- inter | `-- ImplementationBUnitTest.java |-- interface-interface | |-- pom.xml | `-- src | `-- main | `-- java | `-- com | `-- soebes | `-- maui | `-- ut | `-- inter | `-- IFunction.java |-- interface-test | |-- pom.xml | `-- src | `-- test | `-- java | `-- com | `-- soebes | `-- maui | `-- ut | `-- inter | `-- ImplementationUnitTest.java `-- pom.xml
You will find the complete code for this example in the examples distribution under the folder ut-examples-interface.