How to Unit Test an Abstract Class

How to unit test an abstract class? Or a whole class hierarchy that depends on that abstract class? Let’s see.

Unit testing an abstract class

Imagine you work on a people software in a university and have the following code:

In this example, Student and Professor share common functionality, and so you decide to extract it into a Person abstract base class:

This version looks much better because it follows the DRY principle.

Now, the question is — how to test it?

There are two options:

  • Unit test all classes — When you test each class separately (Student, Professor, and Person)
  • Unit test only concrete classes — When you test only the non-abstract classes (Student and Professor)

Let’s discuss them separately.

Test class per each production class

Testing each class in the hierarchy provides the benefit of not repeating your tests. Both Student and Professor derive the GetSignature() method from the base Person class, and so it makes sense to cover that base class directly.

Of course, you can’t instantiate an abstract class, but you can create a mock on top of it, and ask that mock to reuse the non-abstract methods of that class. With Moq, you can do it like this:

Overall, you will get one test class per each class in the hierarchy:

I’ll call this approach test class per each production class.

Test class per concrete production class

The second approach is to test only the concrete classes in the hierarchy: Student and Professor. In this case, you will only have two test classes, StudentTests and ProfessorTests, but you will have to duplicate tests related to the GetSignature() method.

So, which approach is better and why?

The answer is: always test only concrete classes; don’t test abstract classes directly. The reason is that abstract classes are implementation details. From the client perspective, it doesn’t matter how Student or Professor implement their GetSignature() methods. They could derive it from a base class like in our case, but they could also just implement their own copy of it.

Targeting tests at the abstract base class binds them to the code’s implementation details. This, in turn, makes those tests fragile.

The fragility becomes self-evident when you start to customize the base class’s functionality. For example, let’s say that we want each derived class to have its own closing phrase, not just "Regards". For that, we introduce another abstract method:

Notice that Student and Professor still have their closing phrase as "Best regards", so the observable behavior of these classes didn't change. But the test has broken anyway. We have to add the additional setup line in order to fix the test:

Unit testing abstract classes leads to the same consequences as unit testing private methods. In fact, these two practices are essentially the same anti-pattern. Both couple your tests to implementation details and therefore increase the noise you have to deal with after each refactoring.

Here’s the same code sample represented with a private method:

You wouldn’t unit test the private GetSignature() method, would you? Nor should you test abstract base classes.

So, the approach to choose here is test class per concrete production class, where you create a test class per each concrete class of the hierarchy.

But doesn’t it lead to test duplication, you might ask? It does. It’s not a bad thing, though. The Student and Professor aren't the same class, and be tested separately. The fact that they share some common functionality is just an implementation detail, which should be of no concern to your tests. Your tests should always view the system under test as a black box.


Subscribe to read more articles like this:

Originally published at

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store