PHP Testing Tutorial: Mocks, Doubles, Dummies and Stubs
Chris recently joined us during Codementor’s Office Hours, and some of the users asked about testing doubles.
The text below is a summary done by the Codementor team and may vary from the original video and if you see any issues, please let us know!
Do you advocate a lot of mocks? If so, do you ever get the feeling that you aren’t actually testing anything? How do you get past this feeling?
Yes, I do use mocks. I believe mocks are a really good way to tell if your code is overly complex. If you’re having to do a lot of mocks in order to let a testing scenario work, chances are you have an object that you’re testing that is doing too much. Everyone is familiar with the “God” object idea, which has large classes with 20~30 methods on them. If you start looking at what the object is responsible for doing and how the methods are supposed to be manipulating the state of the object, you’ll quickly realize you have some design mistakes.
People talk about code smells. Having to do excessive mocking is a test smell. It means you have a test scenario that’s really complicated and the object you’re trying to test can’t do it without a lot of help. I do use mocks because mocks are the only way to test third-party things that aren’t under your control (e.g. database connections, calls to remote API) and puts them into a proper state as a dependency. Altogether, I mock anything I can’t control, and I try to look and see if there are ways to create a real version of a dependency with the test for things I can control. However, excessive mocking is a sign there is a problem with the code itself.
Can you talk about the differences between Doubles, Dummies, Stubs, Spies, Mocks & Fakes and when to use each one?
In the PHP community, these are all known as mocks because the tools says get mocks. Mockery is my favorite mock tool.
There are two types of test doubles the PHP community mostly uses: dummies and stubs. A dummy creates a mock of an object that just has to stand in because you need that type of object to exist as a dependency, not because you need it to do anything. You just need it to exist to satisfy a parameter check as it’s passed around. A stub creates a test double where I’ll tell it we have this test object that’s pretending to be another thing, I know that I’m expecting specific methods to be called, and when they are, I’m expecting specific results to come back.
Other posts in this series with Chris Hartjes:
- PHP Office Hours: How to Get Started on PHP Testing
- PHP Tutorial: How to Test Message Queues and Event-Driven Systems