Mock, Stub, or Spy? What’s the Difference, and When Should I Use Each?

Most developers have probably heard of mocks, stubs, and spies in the world of test doubles. There is often confusion about the difference between the three and when you want to use them. I am here to help clear things up.

Stubs

Stubs are the simplest form of the three test doubles. They resemble the actual code they are replacing, but they always respond with the same static response regardless of input. Generally, it is best to use a stub when you don’t care what the doubled entity’s behavior is. You only want it to execute without causing an exception.

Spies

Spies are almost the opposite of stubs. They allow the doubled entity to retain its original behavior while providing information about how it interacted with the code under test. The spy can tell the test what parameters it was given, how many times it was called, and what, if any, the return value was.

Spies may also be used to stub or mock a small piece of the doubled entity while leaving the rest of that entity’s behavior in place. For example, if you have a class with multiple functions, a spy would allow you to stub out one of those functions and leave the rest of the class behaving as normal.

Mocks

Mocks are the most powerful of the test doubles. They allow complete control over the doubled entity and provide the same information a spy provides regarding how the entity has been interacted with. Mocks are configured before the code under test is executed to behave however we would like.

There are all kinds of things you can configure your mocks to do. Some examples include:

  • Return an expected value if the correct parameters are given.
  • Return one value on the first call and a different value on the second call.
  • Throw an exception.

Mocks, Stubs, and Spies: Understanding Your Tools

Understanding the tools available to you will allow you to write better, more readable tests. However, not all test double frameworks operate the same way and may have different definitions or behaviors for various test doubles. It’s important to understand how the particular testing framework you are using in your project operates.