Yeda AI Tips · #095

Español

The Tautology Mock

This test passes even if you delete all your code. That's the signature of a tautology mock: the mock returns the exact value the test then asserts, so the mock is answering its own question. The suite stays green, coverage looks fine, and the production code never runs. AI coding assistants generate this pattern constantly — asked to "add a test," they stub every dependency and assert the stub — so you need a fast way to spot it.

Anatomy of a test that tests nothing

def test_get_total(mocker):
    mocker.patch("cart.compute_total", return_value=42)
    assert get_total(cart) == 42   # asserts the mock, not the code

Trace the data: the value 42 enters through the mock and exits through the assertion without touching a single line you wrote. compute_total could contain a bug, an exception, or nothing at all — the test can't tell. In Google's testing vocabulary these are close cousins of change-detector tests: tests that mirror the implementation, break on every refactor, and never catch a real defect.

The 10-second detector

One question exposes almost every tautology mock: could this test fail? Concretely:

  1. Delete-the-body check. Replace the function under test with return 42 (or comment out its body if a mock supplies its output). Still green? The test verifies nothing.
  2. Red-first check. A legitimate new test fails before you write the code — that's the red step of red-green-refactor. If a fresh test passes on first run, it isn't testing anything.
  3. Trace the asserted value. If the expected value appears twice in the test file — once in a return_value, once in an assert — and nowhere in between does production code transform it, you have a tautology.

What to use instead

SituationReach forWhy
Pure logic, cheap dependenciesThe real implementationHighest fidelity; refactors don't break tests
Slow/external dependency (DB, API)An in-memory fake with working behaviorExercises real call paths without the network
You must verify an interaction happenedA mock — asserting the call, not an echoed valueBehavior verification is the one job mocks do well
Mocking anywayautospec=True / specThe mock rejects calls the real API would reject

Martin Fowler's distinction is the key: a fake has a working implementation (an in-memory repository that really stores and retrieves), while a stub provides canned answers. Fakes can be wrong in interesting ways — which is exactly what makes tests against them meaningful. Google's testing team has pushed the same line for a decade: prefer real implementations, then fakes, and mock only what you can't run.

Power-user moves

Resources

Building an AI feature? Yeda AI designs, audits, and ships production LLM systems.

Talk to us · Read the blog