[java] How to test abstract class in Java with JUnit?

I am new to Java testing with JUnit. I have to work with Java and I would like to use unit tests.

My problem is: I have an abstract class with some abstract methods. But there are some methods which are not abstract. How can I test this class with JUnit? Example code (very simple):

abstract class Car {

    public Car(int speed, int fuel) {
        this.speed = speed;
        this.fuel = fuel;
    }

    private int speed;
    private int fuel;

    abstract void drive();

    public int getSpeed() {
        return this.speed;
    }

    public int getFuel() {
        return this.fuel;
    }
}

I want to test getSpeed() and getFuel() functions.

Similar question to this problem is here, but it is not using JUnit.

In JUnit FAQ section, I found this link, but I don't understand what the author want to say with this example. What does this line of code mean?

public abstract Source getSource() ;

This question is related to java junit abstract-class

The answer is


You could do something like this

public abstract MyAbstractClass {

    @Autowire
    private MyMock myMock;        

    protected String sayHello() {
            return myMock.getHello() + ", " + getName();
    }

    public abstract String getName();
}

// this is your JUnit test
public class MyAbstractClassTest extends MyAbstractClass {

    @Mock
    private MyMock myMock;

    @InjectMocks
    private MyAbstractClass thiz = this;

    private String myName = null;

    @Override
    public String getName() {
        return myName;
    }

    @Test
    public void testSayHello() {
        myName = "Johnny"
        when(myMock.getHello()).thenReturn("Hello");
        String result = sayHello();
        assertEquals("Hello, Johnny", result);
    }
}

If you need a solution anyway (e.g. because you have too many implementations of the abstract class and the testing would always repeat the same procedures) then you could create an abstract test class with an abstract factory method which will be excuted by the implementation of that test class. This examples works or me with TestNG:

The abstract test class of Car:

abstract class CarTest {

// the factory method
abstract Car createCar(int speed, int fuel);

// all test methods need to make use of the factory method to create the instance of a car
@Test
public void testGetSpeed() {
    Car car = createCar(33, 44);
    assertEquals(car.getSpeed(), 33);
    ...

Implementation of Car

class ElectricCar extends Car {

    private final int batteryCapacity;

    public ElectricCar(int speed, int fuel, int batteryCapacity) {
        super(speed, fuel);
        this.batteryCapacity = batteryCapacity;
    }

    ...

Unit test class ElectricCarTest of the Class ElectricCar:

class ElectricCarTest extends CarTest {

    // implementation of the abstract factory method
    Car createCar(int speed, int fuel) {
        return new ElectricCar(speed, fuel, 0);
    }

    // here you cann add specific test methods
    ...

My way of testing this is quite simple, within each abstractUnitTest.java. I simply create a class in the abstractUnitTest.java that extend the abstract class. And test it that way.


With the example class you posted it doesn't seem to make much sense to test getFuel() and getSpeed() since they can only return 0 (there are no setters).

However, assuming that this was just a simplified example for illustrative purposes, and that you have legitimate reasons to test methods in the abstract base class (others have already pointed out the implications), you could setup your test code so that it creates an anonymous subclass of the base class that just provides dummy (no-op) implementations for the abstract methods.

For example, in your TestCase you could do this:

c = new Car() {
       void drive() { };
   };

Then test the rest of the methods, e.g.:

public class CarTest extends TestCase
{
    private Car c;

    public void setUp()
    {
        c = new Car() {
            void drive() { };
        };
    }

    public void testGetFuel() 
    {
        assertEquals(c.getFuel(), 0);
    }

    [...]
}

(This example is based on JUnit3 syntax. For JUnit4, the code would be slightly different, but the idea is the same.)


As an option, you can create abstract test class covering logic inside abstract class and extend it for each subclass test. So that in this way you can ensure this logic will be tested for each child separately.


Create a concrete class that inherits the abstract class and then test the functions the concrete class inherits from the abstract class.


You can instantiate an anonymous class and then test that class.

public class ClassUnderTest_Test {

    private ClassUnderTest classUnderTest;

    private MyDependencyService myDependencyService;

    @Before
    public void setUp() throws Exception {
        this.myDependencyService = new MyDependencyService();
        this.classUnderTest = getInstance();
    }

    private ClassUnderTest getInstance() {
        return new ClassUnderTest() {    
            private ClassUnderTest init(
                    MyDependencyService myDependencyService
            ) {
                this.myDependencyService = myDependencyService;
                return this;
            }

            @Override
            protected void myMethodToTest() {
                return super.myMethodToTest();
            }
        }.init(myDependencyService);
    }
}

Keep in mind that the visibility must be protected for the property myDependencyService of the abstract class ClassUnderTest.

You can also combine this approach neatly with Mockito. See here.


You can not test whole abstract class. In this case you have abstract methods, this mean that they should be implemented by class that extend given abstract class.

In that class programmer have to write the source code that is dedicated for logic of his.

In other words there is no sens of testing abstract class because you are not able to check the final behavior of it.

If you have major functionality not related to abstract methods in some abstract class, just create another class where the abstract method will throw some exception.


I would create a jUnit inner class that inherits from the abstract class. This can be instantiated and have access to all the methods defined in the abstract class.

public class AbstractClassTest {
   public void testMethod() {
   ...
   }
}


class ConcreteClass extends AbstractClass {

}

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to junit

Eclipse No tests found using JUnit 5 caused by NoClassDefFoundError for LauncherFactory How to resolve Unneccessary Stubbing exception JUnit 5: How to assert an exception is thrown? How do I mock a REST template exchange? Class Not Found: Empty Test Suite in IntelliJ Unable to find a @SpringBootConfiguration when doing a JpaTest Failed to load ApplicationContext (with annotation) Example of Mockito's argumentCaptor Mockito - NullpointerException when stubbing Method Spring jUnit Testing properties file

Examples related to abstract-class

invalid new-expression of abstract class type Class is not abstract and does not override abstract method When to use: Java 8+ interface default method, vs. abstract method Spring can you autowire inside an abstract class? Abstract Class:-Real Time Example How should I have explained the difference between an Interface and an Abstract class? When do I have to use interfaces instead of abstract classes? Is it possible to make abstract classes in Python? Abstract Class vs Interface in C++ How do you handle a "cannot instantiate abstract class" error in C++?