Since learning to test applications I have always used packages like Mockery or PHPUnit to create mocks objects. I have always found mocking to be a complicated subject and find my tests which involve mocks can be hard to read.
I have never questioned if there was a more basic way of mocking until I watched episode 24 of Clean Code. In this episode Uncle Bob demonstrates creating mock objects by extending the original class. This episode prompted me to test which technique I prefer for a small and simple project.
In my example I have written a Greeter class that will return a different greeting depending on the time of day. “Good morning” between 5am and 12pm, “Good afternoon” between 12pm and 5pm and “Good evening” for the rest of the day. To predict the returned greeting we are going to have to mock out the Greeter class’s dependency on the DateTime object.
Writing the mock for the DateTime object was easy. I extended the class overriding the method I wanted to mock. Then I stored all the arguments passed to the method in a public variable. Finally I made the method return a value of another predefined public variable.
In the following test we use the DateTimeMock to force different greetings out of our Greeter class and check the mocks public variables to assert the mock was called correctly.
In this test we setup up by;
- Creating the DateTimeMock.
- Setting the return value.
- Passing the mock to the class we are testing.
Then call the greetUser method.
Then we assert we got;
- The expected greeting.
- The Greeter called the mock the correct amount of times.
- he Greeter passed the mock the expected argument.
Here is the same test using PHPUnits mocking class.
To me the test code in the first example looks simpler, it also follows the three A’s of testing, Arrange, Act and Assert. When using mocking frameworks I feel the syntax forces us to muddle our assertions in with our arrangements. Over large projects maintaining lots of mock classes might become a chore. But in this project I feel creating your own mocks increases readability.
To see the full example please visit the project on Github.