Mocking is a term that comes up often when we talk about unit testing. What does it mean?
The verb “mock” has several definitions, but only one relates to how we use it in software engineering:
a: to imitate (someone or something) closely: mimic
mockingbird was mocking a cardinal —Nelson Hayes
Mocking means replicating the behavior of something. We replace an object with a mock for testing purposes.
Sometimes there is debate over the differences between a mock, a stub, and a fake. We’ll cover all three, with an emphasis on mocking and how you can use it to improve how you design and test your code.
Mocking Defined
Mocking is creating an object that mimics the behavior of another object. It’s a strategy for isolating an object to test it and verify its behavior.
Definitions of mocking differ over whether a mock must verify behavior. However, Fowler calls mocks “objects pre-programmed with expectations which form a specification of the calls they are expected to receive.” Yet Pivotal says they are “self-verifying spies.” Their definitions are good enough for me.
So let’s expand our initial definition:
Mocking is creating an object that mimics another and setting it with expectations about how it will be used.
“Regular” Unit Testing
Regular unit testing verifies results. A typical example is writing tests for a calculator. A method that adds two integers can be verified by passing it 2 and 2 and checking for 4.
A calculator is a unit testing nirvana. If all tests were as simple as a finite set of inputs and a computed output, verifying behavior would be simple. But even in an imaginary functional utopia, objects interact with the outside world. We need a way to keep our unit tests isolated.
Isolation
Isolation is a critical testing concept. When we test an object, it should be separated from other objects and external dependencies.
With the calculator example, this is easy. But it’s more likely that objects will interact with each other and with external dependencies. Isolation is a vital testing goal that often creates the need for mocking.
If we create an object that interacts with a database, making the database a test dependency is not acceptable. We create an object that mimics the database interface.
But we don’t only isolate from external dependencies. It’s a best practice to confine unit tests as much as possible to one object at a time. When our tests separate components, fixing new problems as they occur is easier.
Imagine moving to a new compiler version and discovering a handful of broken tests. If each test represents a single object, fixing them is simple. If the tests touch three or four objects, repairing the problems is more difficult.
Stubbing and Faking
A stub is an object that mimics another, but with predefined or “canned” responses. We use stubs for tests that rely on an interface to provide one or more calls that return void.
Canned responses can go beyond void, though. Suppose we have an object that inserts single records to a SQL database and the result of a successful insert is always “1,” indicating a single row. We can isolate this object with a simple stub.
A fake is a more sophisticated stub. It implements a subset of the behavior that a production object does, but it’s lighter weight. One example is a fake web service or an in-memory database that replaces a remote version.
This post was written by Eric. Eric Goebelbecker has worked in the financial markets in New York City for 25 years, developing infrastructure for market data and financial information exchange (FIX) protocol networks. He loves to talk about what makes teams effective (or not so effective!)