liveBook · Manning

Test double

As explained in 100 Go Mistakes and How to Avoid Them

A substitute component used in testing in place of a real dependency or collaborator.

When Cache.TrimOlderThan calls time.Now directly, tests depend on wall-clock timing and can become brittle. Inject a func() time.Time that returns a fixed instant to make trimming tests deterministic. Prefer a Cache dependency over a mutable global clock, which shares state and prevents tests from running in parallel. section 11.6

func TestCache_TrimOlderThan(t *testing.T) {
    events := []Event{                                         #1
        {Timestamp: parseTime(t, "2020-01-01T12:00:00.04Z")},
        {Timestamp: parseTime(t, "2020-01-01T12:00:00.05Z")},
        {Timestamp: parseTime(t, "2020-01-01T12:00:00.06Z")},
    }
    cache := &Cache{now: func() time.Time {                    #2
        return parseTime(t, "2020-01-01T12:00:00.06Z")
    }}
    cache.Add(events)
    cache.TrimOlderThan(15 * time.Millisecond)
    // ...
}
 
func parseTime(t *testing.T, timestamp string) time.Time {
    // ...
}

Fix the clock at a known instant while testing event trimming. section 11.6

How 100 Go Mistakes and How to Avoid Them covers it

How deep it goes
Compares an injected clock function with mutable global state and caller-supplied time, without detailing broader clock abstractions.
Examples
Uses Cache.TrimOlderThan with fixed timestamps and a fake clock to test event trimming.
What you can do after
Apply function-based dependency injection to make time-dependent Cache tests deterministic.
How it connects
Connects dependency injection, unit testing, test isolation, and Go's time API.

Also explained in

Compare how 6 books explain test double →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Go Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.