0

At the moment I have an abstract class which implements an interface. All implementations extend the abstract class to make there own implementation of the interface methods.

The abstract class holds methods which are the same for each implementation f.e. an execute method. I don't want to include the same 'execute' test for each implementation class.

I can successfully test the execute method in the abstract class by creating a test class for one of the implementation classes. The problem is that there will be more classes extending this abstract class and I don't want to write the same execute test in each of those classes.

I would like to somehow test the execute method from the abstract class only once in a specific test class so I can test only the implementation logic of all the other classes.

Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63

3 Answers3

0

You can create a test class for your abstract class, too. Although you can't instantiate the abstract class directly, you can still create a concrete implementation class within your test file, just for testing the abstract class, implementing the required methods. You can get an instance for testing e.g. using an anonymous class:

AbstractClassType x = new AbstractClassType() {
    @Override
    public void doSomething() {
        // ...
    }
};
vlumi
  • 1,321
  • 1
  • 9
  • 18
0
public interface BlaInterface {
    public String getData();
}

public abstract class AbstractBla implements BlaInterface {

    // methot to test only once and not for each class extending this
    public void execute() {

        // do some stuff which is the same for each extending class
        getData();
    }
}

public class BlaBla extends AbstractBla {

    public String getData() {
        return "Blabla";
    }
}

So F.E. the above classes I can test the execute() method by testing the BlaBla class. But there will be more classes extending the abstract class and I find it ugly to put the execute() test just random in one of those classes.

So I would like an abstract test for the execute and other test classes just for testing getData f.e.

Fábio Nascimento
  • 2,644
  • 1
  • 21
  • 27
0

You can also create a parameterized test class, which takes the instances with the expected result as input and performs the tests. (However, if you have much verification logic that strongly differs between the different instances, the approach by @vlumi to create an abstract test class might work better, because you can move the verification logic into abstract methods.)

public class MyParameterizedTests {

    @ParameterizedTest
    @MethodSource("getTestData")
    public void test(TestData data) {
        assertEquals(data.expectedResult, data.instance.compute());
    }

    public static TestData[] getTestData() {
        return new TestData[] { new TestData(new X(), "x"), new TestData(new Y(), "y") };
    }
}

class TestData {
    public MyInterface instance;
    public String expectedResult;

    public TestData(MyInterface instance, String expectedResult) {
        this.instance = instance;
        this.expectedResult = expectedResult;
    }
}

interface MyInterface {
    String compute();
}

class X implements MyInterface {

    @Override
    public String compute() {
        return "x";
    }
}

class Y implements MyInterface {

    @Override
    public String compute() {
        return "y";
    }
}
nrainer
  • 2,542
  • 2
  • 23
  • 35