What are fakes, stubs and mocks?
Tags: beginners, csharp, testing
Published: 2021-06-07 15:38:53

_I originally posted an extended version of this post [on my blog](https://canro91.github.io/2021/05/24/WhatAreFakesInTesting/) a couple of weeks ago. It's part of a series I've been publishing, called "Unit Testing 101"_

Do you know what are fakes? Are stubs and mocks the same thing? Let's see what are the differences between them.

## Fakes

The best analogy to understand fakes are flight simulators. With a flight simulator, teachers can recreate flight and environment conditions to train and test their pilot students in controlled scenarios.

**Fakes are like flight simulators**. Fakes are classes or components that replace external dependencies in your tests. With fakes, you can return values, throw exceptions or record method calls to test the code around it. Fakes create the conditions to test our code in controlled scenarios.

<figure>
<img src="https://images.unsplash.com/photo-1539109523166-85417acfcdb7?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=400&ixid=MnwxfDB8MXxhbGx8fHx8fHx8fHwxNjE5NTQ0MDA0&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=600" alt="Two men sitting on aircraft control panel" />

<figcaption>Fakes are like "test" simulators. Photo by <a href="https://unsplash.com/@jan_huber?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Jan Huber</a> on <a href="https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a></figcaption>
</figure>

## Mocks vs Stubs

Now that we know what fakes are, let's see two types of fakes: mocks and stubs.

Fakes represent a broad category of test "simulators". Mocks and stubs are two types of fakes.

**Stubs provide values or exceptions to the code under test and mocks are used to assert that a method was called with the right parameters**.

### OrderService example

To better understand the difference between mocks and stubs, let's use an example. Let's process online orders with an `OrderService` class. 

This `OrderService` checks if an item has stock available to then charge a credit card. Imagine it uses an online payment processing software to take payments and an API request to a microservice to find the stock of an item. We use two interfaces, `IPaymentGateway` and `IStockService`, to represent the two dependencies. Something like this, 

```csharp
public class OrderService 
{
    private readonly IPaymentGateway _paymentGateway;
    private readonly IStockService _stockService;

    public OrderService(IPaymentGateway paymentGateway, IStockService stockService)
    {
        _paymentGateway = paymentGateway;
        _stockService = stockService;
    }

    public OrderResult PlaceOrder(Order order)
    {
        if (!_stockService.IsStockAvailable(order))
        {
            throw new OutOfStockException();
        }

        _paymentGateway.ProcessPayment(order);

        return new PlaceOrderResult(order);
    }
}
```

To test the `OrderService` class, we should check two things. It should throw an exception if the purchased item doesn't have stock. And, it should take a payment if the purchased item has enough stock.

Let's write a test for the scenario of an item in stock.

### Fake for inventory

First, we need a fake that returns stock available for any order. Let's call it: `AlwaysAvailableStockService`. It looks like this:

```csharp
public class AlwaysAvailableStockService : IStockService
{
    public bool IsStockAvailable(Order order)
    {
        return true;
    }
}
```

As its name implies, it will always return stock no matter the order we pass.

### Fake for payment gateway

Second, the `OrderService` works if it charges a credit card. But, we don't want to charge a real credit card every time we run our test. That would be expensive!

Let's use a fake to record if the payment gateway was call or not. Let's call this fake: `FakePaymentGateway`. It looks like this:

```csharp
public class FakePaymentGateway : IPaymentGateway
{
    public bool WasCalled;

    public void ProcessPayment(Order order)
    {
        WasCalled = true;
    }
}
```

It has a public field `WasCalled` we set to `true` when the method `ProcessPayment()` is called.

Now that we have the `AlwaysAvailableStockService` and `FakePaymentGateway` in place, let's write the actual test.

```csharp
[TestClass]
public class OrderServiceTests
{
    [TestMethod]
    public void PlaceOrder_ItemInStock_CallsPaymentGateway()
    {
        var paymentGateway = new FakePaymentGateway();
        var stockService = new AlwaysAvailableStockService();
        var service = new OrderService(paymentGateway, stockService);

        var order = new Order();
        service.PlaceOrder(order);

        Assert.IsTrue(paymentGateway.WasCalled);
    }
}
```

The `AlwaysAvailableStockService` fake is there to provide an indirect input value for our test. It's an stub. And, the `FakePaymentGateway` is used to assert that the `OrderService` made a call to charge a credit card. It's a mock. Actually, we could call it `MockPaymentGateway`.

Voilà! Those are the difference between stubs and mocks. Again, fakes are like test "simulators". Stubs provides values and mocks are used to assert. Next time, you work with external dependencies in your tests, ask if you need a stub or a mock. They're not the same thing.

***

_Upgrade your unit testing skills with my course: [Mastering C# Unit Testing with Real-world Examples](https://www.udemy.com/course/mastering-csharp-unit-testing-with-real-world-examples/?referralCode=8456B1B78E2EDE923174) on Udemy. Practice with hands-on exercises and learn best practices by refactoring real-world unit tests._

_Happy testing!_