A test double is a generic term for any object, service, or component that replaces a real system dependency during automated testing to isolate the unit under test (UUT) and control its environment. This practice is central to unit testing and integration testing, enabling developers to verify logic in a deterministic, repeatable manner without relying on external systems that may be slow, unstable, or non-existent. Common types include mocks, stubs, fakes, spies, and dummies, each serving a specific role in simulating interactions.
Glossary
Test Double

What is a Test Double?
A foundational concept in automated testing for isolating components and controlling dependencies.
The primary purpose of a test double is to provide isolation and determinism. By substituting a real database, API, or complex module, testers can inject specific responses, simulate error conditions, and verify interaction patterns (e.g., how many times a method was called). This is crucial for Test-Driven Development (TDD) and building reliable Automated API Testing Suites. Effective use of doubles, alongside practices like contract testing, ensures that integrations between components, such as an AI agent and an external tool, behave correctly as defined in their shared specifications.
Key Types of Test Doubles
A test double is a generic term for any object or component used in place of a real system dependency during testing to isolate the unit under test and control its environment. The following are specific implementations of this concept, each with distinct responsibilities and use cases.
Dummy
A Dummy is the simplest form of test double. It is an object passed to the system under test but never actually used. Its sole purpose is to satisfy a method's parameter list.
- Purpose: To fill mandatory parameters where the actual value is irrelevant to the test.
- Characteristics: Often
null, an empty object, or a primitive default value. - Example: Passing a
nullUserobject to a method when testing aLoggerclass that doesn't interact with the user data.
Stub
A Stub provides canned answers to calls made during the test. It is programmed to return specific, hard-coded data in response to method calls, overriding the real dependency's behavior.
- Purpose: To control the indirect inputs to the system under test.
- Characteristics: Contains no logic; returns predefined data. Does not respond to anything outside its programmed responses.
- Example: A stub for a
WeatherServicethat always returns"Sunny"to test how aTripPlannerbehaves under good weather conditions.
Spy
A Spy is a type of stub that also records information about how it was called. It captures invocation details such as the number of calls, arguments passed, and the order of calls for later verification by the test.
- Purpose: To observe and make assertions about the interactions between the system under test and its dependencies.
- Characteristics: Passively records activity. Can also stub return values if needed.
- Example: A spy on an
EmailSenderto verify that thesend()method was called exactly once with a specific recipient address after a user registration.
Mock
A Mock is an object pre-programmed with expectations about the calls it will receive. It verifies that these expected interactions occur. A test using a mock will fail if the expected calls are not made or are made in the wrong order.
- Purpose: To test the behavior (the outgoing commands) of the system under test.
- Characteristics: Defined by expectations set before the test executes. Verifies those expectations afterward. Often created using a mocking framework (e.g., Mockito, unittest.mock).
- Example: A mock
PaymentGatewaythat expects acharge(amount, card)call with specific arguments. The test asserts this interaction happened.
Fake
A Fake is a working, but simplified and lightweight, implementation of a dependency. It has functional behavior but uses shortcuts unsuitable for production, such as an in-memory database instead of a real SQL database.
- Purpose: To replace a heavyweight, slow, or complex dependency with a functional equivalent that is good enough for testing.
- Characteristics: Contains real business logic but uses simplified infrastructure. It is not a stub—it has real, working internals.
- Example: A
FakeUserRepositorythat stores users in aHashMapinstead of a PostgreSQL database, allowing for fast, isolated data layer tests.
Choosing the Right Double
Selecting the appropriate test double is critical for clear, maintainable tests. Follow this guideline:
- Use a Dummy for unused required parameters.
- Use a Stub to force the system down a specific path (control inputs).
- Use a Spy to query how a dependency was used after the fact.
- Use a Mock to define and verify specific behavioral expectations.
- Use a Fake to replace a complex infrastructure component with a functional, test-friendly version.
Key Principle: Prefer stubs and fakes over mocks when possible, as they test state over interaction, leading to less brittle tests.
Test Double Comparison
A comparison of the five primary types of test doubles, detailing their purpose, implementation complexity, and typical use cases in automated API testing.
| Type | Purpose | Implementation | Realism | Use Case |
|---|---|---|---|---|
Dummy | Fulfill mandatory parameter requirements. | Null or empty placeholder object. | Passing an unused object to a constructor during a unit test. | |
Stub | Provide canned, pre-programmed responses to specific calls. | Hard-coded return values for a subset of methods. | Simulating a simple "success" or "failure" response from an external payment API. | |
Mock | Verify interactions ("how" the unit under test calls its dependencies). | Pre-programmed expectations about method calls (e.g., 'method X must be called once with param Y'). | Ensuring an audit logging service is called exactly once after a transaction. | |
Spy | Record interactions for later verification without enforcing expectations upfront. | Wraps a real object or stub and passively records method invocations and arguments. | Capturing the arguments sent to an email service to verify content, without failing the test if the call isn't made. | |
Fake | Provide a fully functional, but simplified, alternative implementation. | Lightweight, in-memory working implementation (e.g., a fake database or API client). | Replacing a cloud-based NoSQL database with an in-memory hash map for fast, isolated integration tests. |
Frequently Asked Questions
A test double is a generic term for any object or component used in place of a real system dependency during testing to isolate the unit under test and control its environment. This FAQ addresses common questions about their implementation and role in automated API testing.
A test double is a stand-in object or component that replaces a real dependency in a software system during automated testing. It works by implementing the same interface as the real dependency but provides controlled, predictable responses, allowing developers to isolate the unit under test (UUT) from external systems like databases, APIs, or third-party services. By intercepting calls meant for the real component, a test double eliminates non-determinism, network latency, and side effects, creating a hermetic test environment. This isolation is fundamental to unit testing and integration testing within a continuous testing pipeline.
Enabling Efficiency, Speed & Accuracy
Intelligent Analysis, Decision & Execution
We build AI systems for teams that need search across company data, workflow automation across tools, or AI features inside products and internal software.
Talk to Us
Search across company data
Give teams answers from docs, tickets, runbooks, and product data with sources and permissions.
Useful when people spend too long searching or get different answers from different systems.

Automate internal workflows
Use AI to route work, draft outputs, trigger actions, and keep approvals and logs in place.
Useful when repetitive work moves across multiple tools and teams.

Add AI to products and internal tools
Build assistants, guided actions, or decision support into the software your team or customers already use.
Useful when AI needs to be part of the product, not a separate tool.
Related Terms
Test doubles are categorized by their specific purpose and behavior. Understanding these variations is crucial for implementing effective isolation in automated API testing.
Mock
A mock is a test double that verifies interactions by recording and asserting that specific methods were called with expected arguments. It is programmed with expectations about how the unit under test will interact with it.
- Primary Use: Behavior verification.
- Key Trait: Fails the test if expected calls are not made or are made incorrectly.
- Example: In API testing, a mock HTTP client would verify that
POST /userswas called exactly once with a specific JSON payload.
Stub
A stub is a test double that provides predefined, canned responses to calls made during the test. It replaces a real component to control the test's indirect inputs.
- Primary Use: State control.
- Key Trait: Returns fixed data without verifying how it was called.
- Example: A stub for a payment gateway API always returns
{"status": "success"}to test the happy path of a checkout function, regardless of the input amount.
Fake
A fake is a simplified, functional implementation of a dependency that is unsuitable for production but useful for testing. It has working business logic but uses shortcuts.
- Primary Use: Functional replacement.
- Key Trait: Provides actual behavior (e.g., in-memory storage) but with limitations.
- Example: An in-memory database or a lightweight email service that writes to a local log file instead of sending real SMTP packets.
Spy
A spy is a test double that passively records interactions (method calls, arguments) for later inspection by the test. It wraps a real object or another double.
- Primary Use: Interaction recording.
- Key Trait: Allows verification after execution, without enforcing expectations upfront.
- Example: A spy on a logging service captures all
log()calls and their severity levels, allowing the test to assert that an error was logged after a specific API failure.
Dummy
A dummy is a test double passed to satisfy a parameter list but is never actually used. It is often a null, 0, or an empty object.
- Primary Use: Parameter filling.
- Key Trait: No implementation; any call to it is outside the test's scope and may throw an exception.
- Example: Passing an unused
HttpContextobject to a controller method when testing only the request parsing logic.

About the author
Prasad Kumkar
CEO & MD, Inference Systems
Prasad Kumkar is the CEO & MD of Inference Systems and writes about AI systems architecture, LLM infrastructure, model serving, evaluation, and production deployment. Over 5+ years, he has worked across computer vision models, L5 autonomous vehicle systems, and LLM research, with a focus on taking complex AI ideas into real-world engineering systems.
His work and writing cover AI systems, large language models, AI agents, multimodal systems, autonomous systems, inference optimization, RAG, evaluation, and production AI engineering.
Partnered with leading AI, data, and software stack.
How We Work
Custom AI workflows for your Business
One-fit-all AI don't work for modern businesses. At Inferensys, we aim to understand your business & custom requirements; which we use to define most efficient agentic workflows, the data, and the tools for your business.
01
Review the use case
We understand the task, the users, and where AI can actually help.
Read more02
Pick the right approach
We define what needs search, automation, or product integration.
Read more03
Build the first useful version
We implement the part that proves the value first.
Read more04
Improve from there
We add the checks and visibility needed to keep it useful.
Read moreThe first call is a practical review of your use case and the right next step.
Talk to Us