liveBook · Manning

Stub

As explained in The Art of Unit Testing 3e

A stub is a test double that replaces an incoming dependency by providing controlled behavior or data without verifying interactions with it.

A stub is a test double for an incoming dependency: it supplies controlled data or behavior to the code under test. Use it when real time, databases, networks, configuration, or other indirect inputs would make a test slow, difficult to set up, or unreliable. A stub is arranged so the test can focus on the unit’s result, not on the dependency itself. section 3.1 section 1.7.1

The important distinction is what the test asserts. A stub provides an input or simulates an error, but the test does not verify calls made to it. A mock represents an outgoing dependency or exit point, and the test verifies that interaction. Calling every fake a “mock” obscures this difference and can lead to tests that check implementation details rather than behavior. section 4.1 section 4.4

Control time by passing it in

Instead of reading the current day inside a password verifier, pass currentDay as an argument. A test can pass SUNDAY and assert that verification throws a weekend error. The hardcoded day acts as a simple stub: it makes the scenario repeatable and lets the test simulate any day without relying on a time library. section 3.3.1

Listing 3.3 verifyPassword with a currentDay parameter
const verifyPassword2 = (input, rules, currentDay) => {
    if ([SATURDAY, SUNDAY].includes(currentDay)) {
        throw Error("It's the weekend!");
    }
    //more code goes here...
    //return list of errors found..
    return [];
};
 
const SUNDAY = 0, SATURDAY = 6, MONDAY = 1;
describe('verifier2 - dummy object', () => {
    test('on weekends, throws exceptions', () => {
        expect(() => verifyPassword2('anything',[],SUNDAY ))
            .toThrow("It's the weekend!");
    });
});

The listing shows a small JavaScript test that injects a fixed day and checks the resulting behavior. section 3.3.1

Stubs can enter a unit of work through several seams:

  • Pass a plain value or function as a parameter when the dependency is simple. section 3.3.1 section 3.8
  • Inject an object through a constructor or parameter; in JavaScript it only needs the functions the unit calls. section 3.8
  • Use a shared interface in TypeScript when compile-time checking of the dependency shape is useful. section 3.7.3 section 3.8
  • Replace a module when necessary, but recognize that module injection can become fragile when its API changes. section 3.8

A stub can return a normal value, a failure value, or throw an exception so error handling can be exercised deliberately. Controlling dependencies this way can make tests more repeatable and reduce flakiness; for example, a flaky network-dependent test can be converted into a lower-level test by simulating the endpoint. section 3.7.3 section 7.5.1

Do not turn a stub into a mock by asserting that it was called. Such assertions couple a test to internal steps, making it fragile when implementation changes even if the observable behavior still works. Keep stub setup visible near the test when possible; hiding many differently configured doubles in generic setup can make tests harder to read. section 5.6.5 section 9.4

Stubs are not a substitute for every real dependency. For unit tests, they are generally easier to set up and maintain than an in-memory database. But an in-memory database may behave differently from production, while integration tests with the real database provide a different kind of confidence. section 1.7.1

How The Art of Unit Testing 3e covers it

How deep it goes
Defines stubs, contrasts mocks, and details several injection techniques plus their maintainability trade-offs.
Examples
Uses fixed days for password verification, fake time providers, databases, network endpoints, and configuration failures.
What it assumes
Introduces stubs from basic unit-test isolation without requiring prior framework knowledge.
What you can do after
Apply it via parameter, object, constructor, interface, function, or module injection to control indirect inputs.
How it connects
Connects stubs to test doubles, mocks, dependency injection, Dependency Inversion, and integration testing.

Also explained in

Compare how 10 books explain stub →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Art of Unit Testing 3e. The section links point to the parts of the book it draws on.