Mocking Styles in Testing: Narrow vs Broad

December 12, 2025

Summary

Introduction


The Narrow vs Broad mocking discussion helps teams pause and rethink what their tests are actually validating. Are they proving meaningful behavior, or just policing internal implementation?

In this post, we’ll explore both approaches and when each one makes sense.

What Is Mocking and Why It Matters


Mocking is the practice of replacing real dependencies (databases, APIs, services) with controlled test doubles.

The main goals are to:

  • Isolate the unit under test
  • Keep tests fast and deterministic
  • Reduce failures caused by flaky or unavailable external systems

However, the strictness of your mocks determines whether you’re leaning toward a Narrow or Broad mocking style.

A simple analogy:

  • Do you inspect every ingredient used in a recipe?
  • Or do you just check whether the final dish tastes good?

Both approaches have value depending on what you’re trying to prove.

Narrow Mocks Explained


Narrow mocks focus on precise interactions between components.

They verify details such as:

  • Which methods were called
  • The order of those calls
  • The arguments passed
  • How many times each call occurred

Example (JavaScript / Jest)

expect(paymentGateway.charge).toHaveBeenCalledWith(
  user.id,
  100,
  'USD'
);

This test isn’t just checking the outcome it’s asserting how the system behaves internally.

When Narrow mocks shine

  • Critical business rules
  • Financial or compliance-sensitive logic
  • APIs with strict or fragile contracts

Broad Mocks Explained


Broad mocks shift the focus away from interactions and toward observable outcomes.

They care about things like:

  • Returned values
  • State changes
  • User-visible behavior

How the system achieves the result is intentionally treated as an implementation detail.

Example

const result = checkoutService.checkout(user);
expect(result.status).toBe('SUCCESS');

The test doesn’t care which methods were invoked internally only that the checkout succeeded.

When Broad mocks work best

  • Codebases undergoing frequent refactoring
  • High-level business workflows
  • Tests intended to document behavior rather than implementation

Rule of thumb: The closer a test is to business value, the broader it should be.

Pros and Cons


Narrow Mocks

Pros

  • Very precise validation
  • Early detection of contract or interaction changes
  • High confidence in component collaboration

Cons

  • Tests are fragile
  • Higher maintenance cost
  • Makes refactoring harder

Broad Mocks

Pros

  • More resilient to refactoring
  • Tests read like living documentation
  • Easier and cheaper to maintain

Cons

  • Less precise
  • Interaction bugs can go unnoticed
  • Lower confidence in side effects

Concepts That Go in the Opposite Direction


When mocking starts causing more pain than value, these approaches intentionally move away from heavy mocking altogether:

1. Fake Implementations

Use simple in-memory or lightweight real implementations instead of mocks.

2. Integration Tests

Test real components working together databases, APIs, caches instead of isolating everything.

3. Contract Testing

Validate agreements between services without mocking internal logic.

4. Property-Based Testing

Focus on business rules and invariants, not specific call sequences or interactions.

All of these approaches reduce reliance on mocks and increase confidence in real system behavior.

Conclusion


  • Use Narrow mocks when the correctness of interactions is critical.
  • Use Broad mocks when flexibility and behavior matter more than internal details.

The strongest test suites don’t pick one style blindly they combine both approaches intentionally and thoughtfully.

Further Reading