How to Test Abstract PHP Classes With PHPUnit

How do you test abstract classes in PHP? Find out how to test them in this post by using PHPUnit’s getMockForAbstractClass method.

Recently, as I was working refactoring some code in a personal project I’ve been working on, I decided to change one of the classes into an abstract class. The code isn’t all the complex. It converts CSV export files from several European banks (okay, currently two) into YNAB’s import file format, which is itself a CSV file.

I wrote a class for each bank to read the respective bank’s export CSV file. Both of them extend a base reader class, called BaseReaderentirely original, no? It contains several functions which the bank-specific classes:

  1. Shouldn’t need to re-implement; and
  2. Can build upon as they increase in specificity.

Here’s the source:

abstract class BaseReader implements \Countable, BankAccountReader
    protected $data = [];

    protected $reader;

    public function __construct($filename)
        if (is_string($filename)) {
            $this->reader = $this->initialiseFromFilename($filename);

        if (is_resource($filename)) {
            $this->reader = Reader::createFromStream($filename);


    public function count() : int
        return sizeof($this->data);

    public function getBankAccountRecords() : array
        return $this->data;

    public function initialiseFromFilename(string $filename): AbstractCsv
        if (!file_exists($filename)) {
            throw new InvalidFileException('File does not exist');

        if (!is_readable($filename)) {
            throw new InvalidFileException('File is not readable');

        if (filesize($filename) === 0) {
            throw new InvalidFileException('File is empty');

        return Reader::createFromPath($filename, 'r');

Given that, it made sense to me to refactor BaseReader to be an abstract class. This, for a little while, lead to what seemed like a stumbling block: How would I test an abstract class with PHPUnit?

From what I knew of PHPUnit, up until that time, at least, you couldn’t use it to mock abstract classes. Consequently, after I refactored it to be an abstract class, its functionality couldn’t be tested any longer.

As I’m a firm believer in only writing testable code, it seemed like I’d have to revert the refactor and find another approach, such as extracting the methods into a trait.

Thankfully, it turns out that PHPUnit can test abstract classes after all. After a little bit of searching I came across PHPUnit’s getMockForAbstractClass method.

Cheeky book promotion. Skip over it and keep reading, if you're not interested.
Learn the Mezzio Framework's Fundamentals and Start Creating Great Apps - Today! Mezzio Essentials teaches you the fundamentals of PHP's Mezzio framework — the fundamentals that you need — to begin building get paid for applications with the Mezzio framework right away. It’s a practical, hands-on approach, which shows you just enough of about the underlying principles and concepts before stepping you through the process of creating an application. Learn More

If you have a read through the method’s documentation, you’ll see that it says:

The getMockForAbstractClass() method returns a mock object for an abstract class. All abstract methods of the given abstract class are mocked. This allows for testing the concrete methods of an abstract class.

To use it, you don’t have to do much. The following example shows all it takes.

$stub = $this->getMockForAbstractClass(
    [$this->root->url() . '/files/empty.csv']

The first argument is the class that you want to mock. The second is a list of arguments to its constructor. After that, you can set up any of the expected methods, their arguments, and return values, as you usually would, along with any assertions.

In Conclusion

And that’s how to test abstract classes in PHP, using PHPUnit. There’s not a lot to it, but it’s still helpful to know if and when the time comes, to test abstract classes in your code.

Have you used the method previously? Have you had any issues with it? I’d love to hear in the comments.

You might also be interested in...

comments powered by Disqus


Mezzio Essentials. Learn the fundamentals that you need, to begin building applications with the Mezzio framework today!

Latest YouTube Video

Learn how to write SQL queries in PhpStorm