GuideBeginner

Test Doubles and Test Data

Learn to isolate the unit under test from its collaborators with test doubles (dummy, stub, spy, mock, fake), and to handle test data without drowning in setup. This guide continues the Reservo case right where the fundamentals guide left off: now booking and canceling touch the outside world through a `BookingService` that orchestrates four collaborators — a `Clock` for the time, a `PaymentGateway` to charge and refund, an `EmailSender` to confirm, and a `BookingRepository` to persist. That's exactly where doubles become necessary: you can't test against a real payment service on every run. You'll learn the precise vocabulary from Meszaros's taxonomy, how to stub what goes IN to the unit, how to verify with mocks and spies what comes OUT, how to build a fake that actually works, and how to spot "mock hell," where tests get coupled to implementation. It closes with the Builder pattern for test data that reads by intent, and a final project where you choose and justify the right double for each collaborator of the `BookingService`.

64
lessons
8
modules
English · Spanish
available in
Yes
certificate
Free
access
NIEVA

Outcomes

What you'll be able to do

  • Distinguish the unit under test from its collaborators, and understand why you should NOT use a real service (slow, costly, non-deterministic) in a unit test
  • Master the precise vocabulary of test doubles: dummy, stub, spy, mock, and fake (Meszaros's taxonomy), and distinguish state verification from behavior verification
  • Write stubs that control what goes IN to the unit (canned responses) to test happy paths and failure paths, without over-specifying
  • Write mocks and spies that verify what comes OUT of the unit (`unittest.mock`: `Mock`, `assert_called_once_with`, `call_args`), and recognize when that verification goes too far
  • Build a fake that actually works (an in-memory repository) and understand the contract test that keeps it honest against the real implementation
  • Recognize mock hell: tests coupled to implementation that break on every refactor, and the London vs. Detroit schools
  • Use the Builder pattern and other test data tools (object mother, factories, sensible defaults) so a test reads by intent, not by setup noise
  • Choose the right double for each collaborator in a real case (stub for queries, spy/mock for output effects, fake for persistence), and justify the choice

Before you start

What you need to bring

It's for you if...

  • Devs who already completed testing fundamentals/TDD and now need to isolate units that depend on external collaborators (payments, email, persistence)
  • Devs who overuse `unittest.mock` without judgment and end up with brittle suites that break on every refactor
  • Teams that need readable test data instead of objects assembled by hand, line by line
  • Devs who want to decide, with real judgment, when to double a collaborator and when to test it for real

Requirements and materials

  • Testing Fundamentals and TDD guide completed (or equivalent: running pytest, the red-green-refactor cycle, asserts, basic fixtures, parametrize)
  • Basic object-oriented Python knowledge (classes, constructor-based dependency injection)
  • Python 3.14 and pytest 9.1.1 installed locally (`unittest.mock` is part of the standard library)

Content

The syllabus, module by module

Open any of them to see its lessons.

Common questions

What people usually ask

Start whenever you like

Reviews

What students say

These reviews are from enrolled students who completed at least 50% of the course. We moderate reviews only on content grounds (spam, offensive language, personal data), never for being critical or negative.

No approved reviews yet.

Be the first to share your experience!