logo
podcast Podcast
get help Get Unstuck

Better mocking when testing conditional logic

Explicit assertions are easier to read

Joel Clermont
Joel Clermont
2025-03-17

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.

Toss a coin in the jar if you found this helpful.
Want a tip like this in your inbox every weekday? Sign up below 👇🏼
email
No spam. Only real-world advice you can use.