When testing application code, we need to test both paths of conditional logic.
So with a simple if
branch, we'd have one test follow the path where the condition is true, and we'd have a second test that skips the path with a false condition.
But what if the code inside the branch involves a service that we're going to mock?
The way that Mockery works, you only need to define an expectation if your code is going to call a method on the mocked class.
For example:
$this->mock(StripeService::class);
->shouldReceive('createAsStripeCustomer')
->once();
In the other test, where the condition is false, nothing requires us to set up that expectation.
If our logic had a bug and the mocked service was called by mistake, Mockery would throw an exception and our test would still fail.
Is this good enough?
I don't think so. My preference is to be explicit that we do not expect the service to be called:
$this->mock(StripeService::class);
->shouldNotReceive('createAsStripeCustomer');
There are two benefits of this approach:
- If my logic is wrong, and that mocked method is called by mistake, the error will be much more specific.
- When reading the test, especially in combination with the previous test, it's much clearer that we are not expecting the method to be called. I don't have to hold that difference in my head.
Here to help,
Joel
P.S. Wish you could ship new features more quickly without compromising on quality? We can help.