What is the difference between mocking and spying when using Mockito?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
In the realm of unit testing in Java, Mockito stands out as a popular framework that allows developers to write clean and effective tests. Among the capabilities of Mockito, two of its most significant features are mocking and spying. Both functionalities serve the purpose of simulating the behavior of classes to isolate system under test (SUT) from its dependencies. Despite their similarities, mocking and spying are distinct concepts with different use cases.
Mocking
Mocking is the process of creating an object that mimics the behavior of a real object. It allows developers to define the specific responses of the mocked methods without depending on the actual implementation. This is especially beneficial when the actual method involves complex operations, risky side effects, or dependencies that are challenging to set up or control.
Technical Explanation and Example
In Mockito, when you create a mock, you are essentially creating a skeleton that does nothing unless explicitly instructed. Let's look at a simple example:
In the above example, mockedList is a mock object of the List interface. We define that when the get(0) method is called, it should return "Mockito". Other methods, like size(), return default values (e.g., 0 for integers).
Characteristics of Mocking
- Default Behavior: Methods of the mocked object return default values (zero,
null, or false) unless explicitly specified. - Dependency Isolation: Best used when the method under test interacts with external systems or requires complex setup.
- Control: You have complete control over how the mock behaves through configurations.
Spying
Spying, on the other hand, is a technique that allows you to create a partial mock. Unlike mocking, spying involves wrapping a real instance of a class and often is used when you want to use the actual implementation of the class while still verifying method calls or overriding specific behavior.
Technical Explanation and Example
A spy is a real object, but you can modify its behavior as needed. Here's an example:
In the example above, spyList is a spy of list. The actual list is used, but we can still override the behavior of methods. For example, size() returns 100 instead of the actual size due to behavior stubbing.
Characteristics of Spying
- Real Behavior: By default, a spy uses the real object’s code, rather than a default value.
- Overridable: Specific behaviors or method calls can be overridden as needed.
- Verification: You can verify that certain methods were called on the spy using Mockito’s verification features.
Key Differences
Here is a concise summary in table format of the key differences between mocking and spying in Mockito:
| Feature | Mocking | Spying |
| Object Behavior | Does not invoke real method | By default, uses real methods |
| Method Stubbing | Required to define behavior explicitly | Optional; real object methods are default |
| Dependency Isolation | Complete isolation | Partial isolation |
| Use Case | Testing interactions with dependencies | When you want to use part of a real object |
| Default Return Values | Default values (e.g., 0, null) | Actual method returns value unless overridden |
| Verification | Can verify method interactions | Can verify method interactions |
Additional Considerations
Use Cases
- Mocking is ideal for testing new functionalities independently, ensuring the test remains unaffected by outside factors.
- Spying is particularly useful when refactoring or expanding existing codebases, where the behavior of certain methods is complex or crucial to maintain during the tests.
Performance
- Mocking usually incurs less overhead as it avoids real object creation and logic execution.
- Spying might involve more computational resources since it involves real calls and potentially complex logic.
Limitations
- Mocking is less effective when parts of the real implementation are necessary for the test's logic.
- Spying can complicate testing when there are methods that need to be overridden extensively to avoid unwanted side effects.
Practical Tips
- Favor mocking for pure unit tests where dependencies can be completely isolated.
- Consider spying when the internal state management but not the behavior is your test focus, or where complex internal logic is beneficial.
In summary, both mocking and spying are valuable tools in the programmer’s toolkit when writing unit tests, but they serve different purposes and are best suited to different scenarios. Understanding their differences helps optimize test reliability and maintainability.

