Overview

Get started today
Replay past traffic, gain confidence in optimizations, and elevate performance.

When discussing the process of testing an API, one of the most common sets of terms you might encounter are “mocks” and “stubs.” These terms are quite ubiquitous, but understanding exactly how they differ from one another – and when each is the correct method for software testing – is critical to building an appropriate test and validation framework.

In this blog, we’re going to talk about the differences and similarities between mocks and stubs. By the time you finish reading this, you should walk away with a firm understanding of the core approaches each offers, as well as the overall value of building such valuable tools into your testing process.

Understanding Test Doubles

Testing can be done in a variety of ways, but the two most common types of tests are those “to the right” and those “to the left”. When we talk about shifting in a direction in this regard, we are talking about the relationship between testing and deployment.

When you shift right, you shift later in the production process, testing on content that is actually in the production server set. In other words, you’re testing on live systems. When you shift left, however, you are testing earlier in the process – before deployment and certainly before any systems have been pushed to the production end user.

A good test double is a bit like a statue - a mock object that is representative of an element, but predictable in construction and interaction.

In both of these cases, tests can happen either directly on the code or on what is called a test double. A test double is essentially a stand-in that replaces the real components during critical tests. This allows for the isolation and testing of individual components, reducing the risk of the test itself and the likelihood of disrupting the end-user flow.

Stubs and mocks are two crucial types of test doubles that play crucial roles in testing. Testing doubles allow for the verification of application behavior and state and the observation of the overall mechanics of the system. This can also help you form better tests by isolating the specific mechanics and methods of each system, making tests faster and more predictable.

Characteristics of Stubs and Mocks

With all of this in mind, you might be asking yourself – what’s the difference between a stub and a mock? Let’s dive into these topics now.

Stubs

A stub provides predetermined responses to calls made during a test. They are built to validate a method or functionality and are largely passive in nature – they return the data that you build it to return, and that’s about it.

A stub is like a traffic sign - it will always give you the same info regardless of when you look at it.

This is a great solution for testing specific attributes or elements of a system that can be isolated to a discrete part. For example, if you know you are experiencing errors with network handling, you can isolate the actual module of the test code by substituting it with a stub – conversely, if you’re not sure what the error is appearing within, you can substitute parts with “best case” stubs until you find the actual issue.

Stubs can also be used to create behavior that would be experienced in a production environment without actually introducing said environment. You can return canned data when an external API is called, simulate dependencies, create fake database records, and more, allowing for very flexible testing that is largely concerned with object behavior.

Mocks

Mocks, on the other hand, are a much more active element of testing. A mock in this context is a fake object that records method calls and asserts whether an expected interaction actually took place. This can verify interactions and validate that the system is working as it should – or if it is not, suggest where the issue might be arising. This is especially useful in complex interactions that might take place over an extremely complicated flow, as you can track specific issues down to the object and function level.

Mocks are more like traffic lights, providing variable functions and data depending on the inner workings of the overall system.

Mocks are very useful when it comes to validating the interactions between actual objects that are being tested, but they can also be very useful when you want to check adherence to an API contract. If something is supposed to happen, and it doesn’t (or it does, but in an incorrect way), a mock can give you an idea of where in the chain the interaction failed and the frequency of that error across multiple tests and use cases.

Key Differences Between Stubs and Mocks

Although they serve a similar end purpose, there are some critical key differences that set stubs and mocks apart.

  • Stubs focus on one aspect of the software at a time, while mocks focus on the behavior of the software.
  • Stubs are used for state testing, while mocks are used for behavioral testing. For this reason, stubs are often considered relevant to one test or one isolated issue, whereas mocks are considered relevant for more complex implementations or instances where you must verify expectations.
  • Stubs provide predefined responses to calls, while mocks record and validate interactions between the actual database objects.
  • Mocks are more advanced and can track function calls and order, while stubs are limited to producing the same result based on specific inputs.

It’s important to remember that these key differences are generally applicable, but there are some specific use cases or exceptions where mocks or stubs might be used in unique ways. For instance, while stubs typically provide canned answers to simulate interactions within a system, they might serve data depending on specific states – this is a false complexity and, in fact, is still just a canned response.

Stubs and Mocks: A Comparison Table

Let’s distill these differences in use and benefits into a simple table.

Mocks Stubs
Definition Mocks are simulated systems that verify behavior under testing conditions to validate the contract or design of a service. Stubs are dummy objects that return predefined responses to testing requests, serving either as predictable intermediaries or targeted service points.
Purpose Focuses on verifying that the API interactions work as designed. Focuses on providing canned responses and dummy data, allowing providers to test core functionality independent of other external systems.
Scenario for Use Best suited for testing and validating API contracts and integrations, ensuring correct behavior of dependencies and connected systems. Best suited for simulating specific objects or resources when you need to simulate a single isolated API call or interaction.
Complexity Mocks are much more complex than stubs and require more systems to ensure the real-world applicability of findings. Stubs are much simpler to set up but, in turn, are much more simplified and limited in their applicability.
Testing Focus Interaction-based testing. State-based testing.
Real-World Equivalent A test supervisor verifying that steps are followed in an incident by everyone involved. A vending machine that outputs the same item regardless of the situation.

Best Practices for Using Stubs and Mocks

In order to use stocks effectively, you should adhere to some basic best practices.

Firstly, use stubs for setting up conditional elements or predefined data that provide correct arguments or expected parameters for repeatable testing. If you are trying to validate the state of a resource, a stub can provide the same data a million times, allowing you a stable rock from which to validate and test. Mocks, on the other hand, are better for verifying actions and should be used for situations in which more variability is necessary.

Stubs should replicate the production environment when they are not the object being tested. If you are trying to validate the state of an object and you have other stubs in the test that don’t match the production object, your test will not reflect the state of the real object. Accordingly, stubs should be used in a way that mirrors the reality of the system while testing individual elements.

Mocks, on the other hand, can be much freer in their implementation details, especially when they are being used for testing a mock implementation or certain methods that are not in the live production or actual code deployment. This can be used to great effect for feature testing or validating different scenarios using advanced techniques like machine learning and iterative/dynamic data configuration.

A good simulation requires firm understanding of what is being simulated. Accordingly, using stubs and mocks correctly will require an understanding of what you're testing, how you're testing it, and what you want to avoid introducing into the test.

Both mocks and stubs should be used with ample documentation and review. False positives (and false negatives) can be used with both the under and overutilization of these solutions, so you should validate the test itself before relying on the data it produces at scale.

This approach is particularly useful both in unit testing and integration testing. Unit testing involves testing each piece individually, while integration testing involves testing how they all work together. Test doubles help isolate parts of our code from their dependencies. Mocks and stubs are essential tools for simplifying the testing process and improving the quality and reliability of software applications.

When to Use Stubs and Mocks

Figuring out when to use a stub vs. mock is relatively easy if you pay close attention to what is actually being tested:

  • Use stubs when the test suite is simple and hard-coded values aren’t an issue.
  • Use mocks when you need to verify that specific methods are called with particular arguments and ensure that certain interactions occur, especially when testing working implementations or deploying large test suites.
  • Use stubs for domain objects, which should not be highly variable outside of external dependencies.
  • Use mocks to test services that have data flowing through them, emulating your database connections and complex interactions.
  • Mocks focus on behavior verification, while stubs focus on state verification. As such, if you are focused solely on one or the other, the choice is pretty much made for you.
  • Mocks allow you to verify whether specific interactions have occurred, while stubs enable you to test specific outcomes based on pre-defined responses. If you are testing with a reliance on objects pre-programmed with data, you are looking at stubs – if you are testing interactions, third-party library dependencies, or other tests requiring complex interactions between systems, use mocks!

Flexibility and Test Isolation

One key difference to consider between these technologies is their flexibility and the nature of their test isolation. While both mock testing and stub testing provide test isolation, their focuses tend to be slightly different.

Mocks provide greater flexibility by allowing you to specify the expected behavior and interactions of dependencies. Stubs are much more static, providing predictable responses and isolating the unit being tested from its dependencies to ensure reliable results. Accordingly, a mock is best when you are isolating a test on behavior, whereas a stub is best when you are isolating a test on state.

Common Pitfalls to Avoid

Using mocks or stubs can lead to fragile tests if not used correctly. Make sure that you are planning your tests ahead of time, and review your testing systems to make sure you are not introducing false positives or negatives. Fragile tests – that is, tests that are sensitive to changes in code and may break easily – are mitigated largely by being sensible with how many and in what position you place stubs and mocks.

Your testing is only as good as your data - make sure your setup data is valid, and your dummy objects replicate actual structures within your codebase for more effective testing.

Also, consider the validity of your data. Creating a stub that puts out a specific piece of data only gives you a good test if the actual data in production is similar – if your stubs are putting data out that is wildly out of alignment, your testing will be very low quality. The same is true of mocking – make sure that your mocks replicate actual real functionality – “but it worked in testing” is only a valid excuse if the testing was valid to begin with!

Conclusion

Mocks and stubs are essential tools for effective testing strategies in software development and are critical in delivering robust and reliable software at scale. Understanding the key differences between mocks and stubs is crucial for creating robust and reliable unit tests and improving the quality and reliability of their software test lifecycle and production applications.

During this process, you will certainly need to have sensible and usable data. Simulating data isn’t good enough – after all, as stated above, the quality of your data will dictate the quality of your testing. Thankfully, there are solutions such as Speedscale that can solve this problem. Speedscale allows you to capture real production traffic for replay in your testing process, allowing you to create a more cohesive and useful testing process.

Speedscale orange/gray/black Logo

With Speedscale, you can transform real user behavior into realistic local development resources, allowing you to avoid many of the pitfalls of traffic simulation and emulation. The best part of it all is that Speedscale is free to try – if you’re interested in unlocking the benefits of powerful traffic replay, you can sign up for a free trial today!

 

Ensure performance of your Kubernetes apps at scale

Auto generate load tests, environments, and data with sanitized user traffic—and reduce manual effort by 80%
Start your free 30-day trial today

Learn more about this topic