A Short Introduction to Postman
Debugging requests can be a time-consuming process. However, there’s a tool that makes doing so a lot simpler. It’s called Postman. In this tutorial, I step you through its core features and show you how to use them.
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 BaseReader
— entirely original, no?
It contains several functions which the bank-specific classes:
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);
}
$this->reader->setHeaderOffset(static::HEADER_OFFSET);
}
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.
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(
BaseReader::class,
[$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.
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.
Debugging requests can be a time-consuming process. However, there’s a tool that makes doing so a lot simpler. It’s called Postman. In this tutorial, I step you through its core features and show you how to use them.
PhpStorm offers so much functionality. From syntax highlighting to Docker integration, it’s an extremely comprehensive tool. However, have you ever thought of using it to run your unit tests? In this article, I step you through running tests, from an entire suite to an individual test.
If you love using data providers in PHPUnit, but find defining them verbose (and potentially buggy) then you’ll love the attribute-based approach in PHPUnit 10. Learn the essentials in this short post.
Using Codeception as your testing framework of choice? Did you know it’s really easy to test Zend Expressive TableGateway classes? It’s almost painfully easy. This tutorial walks you through, step-by-step.
Please consider buying me a coffee. It really helps me to keep producing new tutorials.
Join the discussion
comments powered by Disqus