PHPUnit: Testing The Constructor
In a previous blog post I explained how you could mock the system under test. This allows you to easily verify if a given method calls other methods in the same class.
What if you wanted to verify this from the constructor?
Normal classes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
The constructor is a magic function in your class and is invoked when you create a new instance of said class. You don’t explicitly call the constructor method.
Being a meticulous developer and trying to reach 100% unit test coverage, I explicitly want to verify if the constructor calls setDoors
. One solution would be the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
First thing I do, is create a mock object for the Car class, but I request that the constructor is not called with disableOriginalConstructor
.
Next I set the expectations for my mock object: verify that the setDoors
method is called with 4 as an argument.
Lastly, through reflection I get a reflection method for the constructor, which I then invoke for the mock object and correct argument.
Abstract classes
For regular classes, the method described above seems straightforward. When dealing with abstract classes, mocking needs some more attention.
PHPUnit provides us with a getMockForAbstractClass
method, which conveniently creates a mock for an abstract class. What’s in a name. Now where the regular getMock
method doesn’t mock any method unless you specify the ones you want, getMockForAbstractClass
by default mocks the abstract methods so you can test the concrete methods.
So far things are logical. If you try the same approach as above for abstract classes, exchanging the ->getMock()
for ->getMockForAbstractClass()
, you end up with a disappointment. The mock tells you that the internal method wasn’t called. Odd. Doing some var_dump-driven-development tells you that the method is called. However, it’s not reflected in the mock.
How to fix?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Tadaa! For an abstract class, we explicitly have to define the list of methods we want to stub.
Come to think of it, this is actually logical behavior, as this is how regular mocking works. What’s not logical, is that it works for normal classes without the list of methods you want to stub. So just to be on the safe side (and to have some kind of pattern), just always provide a list of methods. At least, that’s what I’m going to do from now on.