CodePark/ questions / TDD & test design
START PRACTICINGPRACTICE
Backend question · Backend testing › TDD & test design

What does "test behaviour, not implementation" mean? Give an example of a test that breaks the rule and how you would rewrite it.

It means a test checks what the unit does, as its callers see it, not how it does it inside. Callers see its results and its observable side effects. Then you can refactor freely, and tests fail only when the behaviour really changes.

A test that breaks the rule. It tests UsersService.register and asserts these calls, in this order:

  • repo.findOneBy with { email }
  • bcrypt.hash with 10 rounds
  • repo.create, then repo.save

Now imagine a harmless refactor. You replace the lookup with a unique constraint in the database. Or you replace create plus save with insert. The test breaks, but users still register correctly.

The rewrite. A behaviour test registers a user and checks the results:

  • You can find the user by email.
  • The stored password is not the plain text, and it verifies against the plain text.
  • Registering the same email again fails with a conflict.

The usual warning signs of a bad test are spying on private methods and asserting call order.

  • Assert results and observable side effects, not internal steps.
  • Tests tied to the implementation break on harmless refactors.
  • Example: asserting the order of repository and hashing calls.
  • Warning signs are spying on private methods and asserting call order.