tezvyn:

Mocking in Go: Swap Real Code for Test Doubles

AI-drafted, machine-checkedSource: quii.gitbook.iointermediate

Mocking in Go uses interfaces to swap slow dependencies like `time.Sleep` with fast fakes in tests, keeping your test suite quick. Use it for network calls or database access. The footgun is testing implementation details instead of observable behavior.

WHY IT EXISTS Tests must be fast to provide a quick feedback loop. When a function depends on something slow, like a network call or a timed pause, the tests for that function become slow. This harms developer productivity by making the test-edit-run cycle painful. Mocking was invented to isolate code from slow dependencies, allowing tests to run in milliseconds.

THE MENTAL MODEL Instead of your function depending on a concrete, slow implementation (like the global time.Sleep function), it depends on an interface you define. In your application's main entrypoint, you provide the real implementation that actually pauses. In your tests, you provide a "mock" or "fake" implementation that satisfies the same interface but runs instantly.

HOW IT WORKS The process is dependency injection. First, identify the slow dependency, like time.Sleep. Second, define an interface that describes the necessary behavior, for example, a Sleeper interface with a Sleep() method. Third, refactor your function to accept this interface as an argument. Fourth, create a real struct that implements this interface by calling the actual time.Sleep. Finally, for your tests, create a mock struct that also implements the interface but does nothing or simply records that it was called. This lets your test run without any actual delay.

WHEN TO USE IT Use mocking when testing functions that interact with external systems or dependencies that are slow, non-deterministic, or have side effects. This includes network services, database connections, filesystem operations, and system clocks or timers. The goal is to isolate your function from these external factors to test its logic in a fast and predictable way.

WHEN NOT TO USE IT Avoid mocking dependencies that are already fast, deterministic, and have no side effects, such as pure utility functions. Overusing mocks for simple, internal logic can make tests more complex and brittle than the code they are testing, and they can obscure the actual behavior being tested.

ONE CANONICAL EXAMPLE A Countdown function prints 3, 2, 1, Go!, with a one-second pause between each print. The time.Sleep call makes testing slow. To fix this, you define a Sleeper interface with a Sleep() method. The Countdown function is changed to accept a Sleeper. In main, you pass a real sleeper that calls time.Sleep. In the test, you pass a MockSleeper whose Sleep() method is empty or just increments a counter. This allows the test to verify the countdown logic and output instantly without waiting.

Read the original → quii.gitbook.io

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.