Mocks, Spies, and Stubs: How to Use?
Mocks, Spies, and Stubs are three different types of test doubles that we use in software testing. These are mainly used in unit testing, API testing, etc. We use mocks, stubs, and spies to simulate the behavior of complex, real objects. These tools are essential for isolating the component under test and ensuring that the tests are not affected by external dependencies. Let’s discuss each of these more and how we use them in testing.
Mocks
When testing software, you may need a way to imitate complex parts of your system to check the smaller, more isolated pieces. Let’s consider rehearsing a play. Sometimes, not all actors are available, so you might have stand-ins to help practice scenes. In software testing, mocks are these stand-ins, but for software components.
Mocks are fake versions of real software components that programmers use during testing. They are designed to mimic the behavior of real objects in controlled ways. By using mocks, you can ensure that the part of the software they are testing works correctly without needing the actual software components, which might be unreliable, slow, or difficult to set up for testing.
Why Use Mocks?
Imagine you are developing an app that needs to fetch weather data from an online service. To test the app’s response to different weather conditions, you wouldn’t want to rely on real-time weather data because it’s unpredictable and beyond your control. Instead, you could use a mock to simulate the weather service. You can program the mock to return predefined weather data (like “sunny” or “rainy”) so you can see how your app behaves under those conditions without connecting to the actual weather service.
This approach has several benefits:
How Do Mocks Work?
Mocks work by replacing real objects in your system with fake ones that you create just for your tests. These fake objects are programmed to behave in specific ways. Let’s consider an example: For a function in your code, it needs to call another service, and that service returns the value as either “Yes” or “No”. So, to check your function, you can create a mock of that service which always returns the value “Yes”. With this, you can test your function.
Here’s a simple step-by-step explanation of using a mock:
When We Use Mocks?
There are several situations in which we can use a mock.
Examples of Using Mocks
Let’s consider a Python example using unittest.mock, a popular mocking library:
from unittest.mock import Mock
# Suppose we have a function that checks stock availability
def check_stock(product_id, database):
return database.get_stock(product_id) > 0
# Create a mock database
mock_database = Mock()
# Configure the mock to return a specific value
mock_database.get_stock.return_value = 10
# Use the mock in our function
product_is_in_stock = check_stock("1234", mock_database)
# Verify
assert product_is_in_stock == True
mock_database.get_stock.assert_called_with("1234")
In this example, mock_database is a mock version of a database. We configure it to always return ’10’ when get_stock is called, regardless of the input. We then check that check_stock behaves correctly when get_stock returns a positive number, and we also verify that the right database method was called with the right arguments.
Best Practices
When using mocks, it’s important to follow some best practices:
Spies
Spies are special tools that let you watch how parts of your program behave during tests without stopping them from doing their normal work. They’re like secret agents in your code, watching and recording information silently. Understanding spies can help you ensure your tests are thorough and that your program behaves exactly as expected under various conditions.
A spy is a type of test double, which we can say is a fake version of a function or a method that you use in tests. However, unlike mocks or stubs that replace the whole function with fake behavior, spies wrap the real function, allowing it to run normally while secretly recording information about how it was used. For example, spies can track how many times a function was called or what arguments were passed to it.
Why Use Spies?
Spies are incredibly useful because they give you insight into how your code operates without changing its behavior. Here are some of the main reasons why developers use spies in their tests:
How Do Spies Work?
Implementing spies typically involves the following steps:
When We Use Spies?
Here are several key scenarios where we use Spies:
Examples of Using Spies
Imagine you’re testing a piece of code in a shopping cart application. You want to ensure that when an item is added to the cart, it triggers a function that updates the total price. Here’s how you might use a spy in JavaScript with a popular testing framework like?Jest:
// Function to test
function addToCart(item) {
cart.push(item);
updateTotal(); // We'll spy on this function
}
// Test
test('updateTotal is called when an item is added to the cart', () => {
const spy = jest.spyOn(cart, 'updateTotal');
addToCart({ item: 'Book', price: 9.99 });
expect(spy).toHaveBeenCalled(); // Check if the spy recorded a call to updateTotal
spy.mockRestore(); // Clean up the spy
});
In this test, the spy helps confirm that not only does the addToCart function add the item, but it also correctly calls the?updateTotal?method to update the cart’s total, verifying the interaction without affecting the operation.
Best Practices for Using Spies
Stubs
Stubs are simplified, controlled replacements for complex or unwieldy components your code interacts with. Like actors on a movie set who stand in for stars during the complicated setup of scenes, stubs stand in for real components in your tests, making the testing process smoother and more focused.
A stub is a type of test double – a term used in software testing to describe any object or component that replaces a real component purely for testing purposes. Stubs are programmed to return specific responses to calls made during a test. They don’t attempt to replicate the complete behavior of the component they replace; instead, they provide predetermined responses to specific input.
For example, if your application needs to fetch weather data from an external service, you might use a stub to simulate this service. The stub would return fixed weather data when queried, so you can test how your application behaves with that data without needing to rely on the external service during tests.
Why Use Stubs?
Stubs are particularly useful because they help isolate the part of the system you are testing. This isolation helps you verify that your application behaves correctly with known inputs and can handle various outputs the real component might produce. Here are some key reasons to use stubs:
How Do Stubs Work?
Using a stub typically involves the following steps:
When We Use Stub?
There are several key situations where using stubs is particularly beneficial:
Example of Using a Stub
Consider a simple application that calculates the total cost of items in a shopping cart, including tax, which is retrieved from a tax calculation service. To test this functionality without hitting the actual service, you might use a stub for the tax service:
领英推荐
class TaxServiceStub:
def get_tax_rate(self):
# Always return a fixed tax rate
return 0.05
# In your tests
def test_calculate_total_with_tax():
cart = ShoppingCart(items=[Item(price=100)])
tax_service = TaxServiceStub()
total = cart.calculate_total_with_tax(tax_service)
assert total == 105 # 100 + 5% tax
In this example,?TaxServiceStub?is a stub that simulates the tax calculation service by always returning a fixed tax rate of 5%. This allows the test to focus on the correctness of the calculate_total_with_tax method in the ShoppingCart class.
Best Practices for Using Stubs
Mocks vs. Spies vs. Stubs
Feature: Purpose
Mocks: Primarily used to verify interactions.
Spies: Used to gather information about how a function is called.
Stubs: Used to provide predetermined responses to calls.
Feature: Usage
Mocks: This is to ensure that certain methods are called with the expected arguments.
Spies: To observe method calls and record information without affecting their behavior.
Stubs: To replace complex or unavailable components with simplified ones that return fixed data.
Feature: Functionality
Mocks: Can enforce that expected actions are taken within the code.
Spies: Do not alter the behavior of the function; just track it.
Stubs: Do not track calls or interactions; only return specific responses.
Feature: Control
Mocks: High control: Mocks can dictate the behavior of the test scenario.
Spies: Medium control: Spies allow the original method to execute and record the calls.
Stubs: Low control: Stubs only respond to calls with predefined outputs.
Feature: Interaction
Mocks: It can be used to assert on the method calls and interactions.
Spies: Used to verify that methods were called correctly, but not to enforce it.
Stubs: No verification of method calls; purely a response provider.
Feature: Complexity
Mocks: High: Requires setup to define expected interactions.
Spies: Medium: Requires setup only to record interactions.
Stubs: Low:?Simply return fixed values or states.
Feature: Typical Use
Mocks: To test the interactions between objects in isolation from their dependencies.
Spies: To monitor existing functionality during a test to ensure correct behavior.
Stubs: To simulate external services or components to ensure the tested code runs in isolation.
Tools for Creating Mocks, Spies, and Stubs
Different programming languages and environments have their own tools designed specifically for this purpose. Let’s list a few popular ones in each language.
e
Mocking API calls with testRigor
We know testRigor is not just a web automation tool; it supports different types of testing, such as web and mobile browser testing,?mobile testing,?desktop app testing, API testing,?visual testing,?accessibility testing, etc. Using testRigor, we can mock the API response to test the function of individual API calls. Let’s see an example.
mock api call get "https://dummy.restapiexample.com/api/v1/employees" with headers "a:a" returning body "This is a mock response" with http status code 200
In the example above, any GET calls to the endpoint “https://dummy.restapiexample.com/api/v1/employees” with the headers “a:a” will respond with the testRigor mock, with status ‘200’.
Some useful cases are:
To know how we can do API testing using testRigor, you can read this blog –?How to do API testing using testrigor. Apart from that, testRigor supports automating complex scenarios such as?2-factor authentication,?QR codes,?CAPTCHAs,?email testing, SMS testing,?table data, and more with simple English commands. Find the?top testRigor’s features?here.
Conclusion
Mocks, spies, and stubs are special tools that help us make sure every part of our software works correctly on its own without any problems. Without these tools, it would be tough to check each component separately. By using mocks, spies, and stubs in our tests, we can make our applications more stable and reliable. These tools help developers create clearer and more specific tests, giving us the confidence that our software will work well in different situations. Therefore, it’s always a best practice to use these test doubles to ensure a high-quality application.
Frequently Asked Questions (FAQs)
How do I choose between a mock, a spy, or a stub?
Choosing between Mock, Stub, and Spy depends on the function or method that you need to test. If you need to assert behavior, then you can use mocks. If you need to observe the behavior without altering it, you can go with spies. If you need to isolate the method from external dependencies by providing an expected response, then you can use stubs.
Can mocks, spies, and stubs be used together?
Yes, we can combine these test doubles based on the scenario we are testing. For example, if the scenario is very complex and requires you to isolate, observe, and verify different aspects of the system, then you can use them combined.
--
--
Scale QA with Generative AI tools.
A testRigor specialist will walk you through our platform with a custom demo.
Liseller Cofounder
6 个月Mocks, spies, and stubs are important tools in software testing to ensure reliable results. ?? They help isolate components and make testing more effective. #SoftwareTesting #TestAutomationTools
?? Full Stack Developer | JavaScript Expert | React ? Node ? Next.js ?? Building scalable web solutions | Ex-Wipro"
7 个月Great explanation of the different test doubles in software testing! Mocks, spies, and stubs are crucial tools for creating reliable and isolated tests. This article does a fantastic job of breaking down their roles and usage.Definitely a must-read for anyone looking to enhance their testing strategies. Thanks for sharing this valuable insight!