Test doubles: stubs, spies, mocks and fakes

Testing Mid-level Swift 5.0+ iOS 17+ Reviewed By Alok Singh

Pick the fix

You need to check that send(to:) was called once with the user's email. Which double?

Options
Hint 1 of 1

You need to inspect how it was called.

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A A spy that records each call and its arguments

Correct. The test asserts on the recorded calls.

Why not the others?
  • B A stub. Stubs return answers; they don't record calls.
  • C A fake. A fake works like the real thing, but doesn't track calls unless you add that.
  • D A dummy. A dummy is never used.

30-second answer

Test doubles stand in for real dependencies. A dummy fills a parameter and is never used. A stub returns canned answers. A spy records how it was called so you can assert on it. A mock is set up with expectations and verifies them. A fake is a working lightweight implementation, such as an in-memory store. In Swift you build them from small protocols.

Practise saying it · 45 s. No recording, just a timer

Explain the kinds of test doubles.

Say your answer out loud, then check which of these points you covered:

  • Dummy, stub, spy, mock, fake
  • Protocols make them easy
  • Prefer outcome assertions

Deep dive

Prefer stubs and fakes; assert on outcomes rather than calls when you can.

Spies help when the call itself is the behaviour, like sending an email.

Make doubles final and simple; avoid logic in them.

Swift macros or code generation can create doubles, but handwritten ones are often clearer.

Common mistakes

  • Mocking everything, which ties tests to implementation details.
  • Doubles that need their own tests.

Senior take & follow-ups

Seniors name the double precisely and prefer outcome-based tests.

Follow-up questions

Think of your answer first, then open the hint.

  1. When is a fake better than a stub?

    Show hint

    When behaviour across calls matters, like save then load.

  2. Why prefer outcome assertions?

    Show hint

    They survive refactoring.

Suggest a fix if something here is wrong or out of date.