Automation Testing · Unit & API Tests

Mocking and Test Doubles

Test doubles replace slow or unpredictable dependencies — databases, payment gateways, clocks — so unit tests stay fast and focused.

Intermediate 5 min Lesson 15 of 24
Before you start:Unit Testing with xUnit
0/24 in Automation Testing
On this page · 5 min · Intermediate

Learning objectives#

  • Name the types of test doubles
  • Stub return values
  • Verify interactions with mocks
  • Avoid over-mocking

Explanation#

Dummy: passed but never used. Stub: returns canned answers. Fake: simple working implementation (in-memory repo). Mock: records and verifies calls. Spy: wraps a real object and records calls.

C#: Moq or NSubstitute. JavaScript: jest.fn(), jest.mock().

Mock at boundaries you own (interfaces to email, payment, time). Over-mocking internal details makes tests fragile and less meaningful.

Code example: Stubbing and verifying with Moq#

C#Stubbing and verifying with Moq Illustrative
// dotnet add package Moq
public interface IPaymentGateway { Task<bool> ChargeAsync(decimal amount); }
public interface IEmailSender { Task SendAsync(string to, string subject); }


public class CheckoutService(IPaymentGateway pay, IEmailSender email)
{
    public async Task<bool> PlaceOrderAsync(string customer, decimal total)
    {
        if (!await pay.ChargeAsync(total)) return false;
        await email.SendAsync(customer, "Order confirmed");
        return true;
    }
}


public class CheckoutServiceTests
{
    [Fact]
    public async Task Successful_payment_sends_confirmation()
    {
        var pay = new Mock<IPaymentGateway>();
        pay.Setup(p => p.ChargeAsync(500m)).ReturnsAsync(true);          // stub
        var email = new Mock<IEmailSender>();


        var ok = await new CheckoutService(pay.Object, email.Object).PlaceOrderAsync("asha@example.com", 500m);


        Assert.True(ok);
        email.Verify(e => e.SendAsync("asha@example.com", "Order confirmed"), Times.Once);   // mock
    }
}
Expected output
Passed — no real payment or email was sent, and the test proves the email is sent exactly once.

This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.

Step-by-step explanation#

  1. The payment gateway is stubbed to succeed.
  2. The email sender is a mock.
  3. The service runs with both doubles.
  4. Verify checks the interaction happened once.

Real-world use case#

Checkout logic is tested in milliseconds without calling the real payment provider.

Common mistakes#

Mocking everything

Tests then only check that code calls code. Use fakes or real objects for simple collaborators.

Mocking types you don’t own

Wrap third-party SDKs behind your own interface and mock that.

Best practices#

  • Mock at system boundaries
  • Prefer stubs over strict mocks
  • Use fakes for repositories
  • Verify only important interactions

Remember this#

Stub = canned answer. Mock = verifies calls.

Mock boundaries, not internals.

Wrap third-party SDKs.

Practice exercise#

Your task: Stub ChargeAsync to fail and assert PlaceOrderAsync returns false and sends no email.

Show solution
C# Illustrative
pay.Setup(p => p.ChargeAsync(It.IsAny<decimal>())).ReturnsAsync(false);
// ...
Assert.False(ok);
email.Verify(e => e.SendAsync(It.IsAny<string>(), It.IsAny<string>()), Times.Never);

Mini quiz#

Mocking and Test Doubles quizMultiple choice Question 1 of 1

Which test double verifies that a method was called?

Score so far: 0/0

Want more? Practise all Automation Testing MCQs · Automation Testing interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.