Mocks vs Stubs vs Fakes In Unit Testing

When it comes to unit testing, I’m a lover of mocks. I can’t get enough of them. Infact, I wrote an entire “TestingContext” helper to help me “auto mock” my classes which I think you should definitely check out if you haven’t already! I can’t think of a unit testing project that doesn’t utilize the .NET library Moq in some way.

But! In very rare cases, I use stubs, and in even rarer cases (But still sometimes), I use fakes. Often when you are trying to test “framework” code such as creating a custom ASP.NET Core Filter or Middleware, you have no option but to use stubs and/or fakes.

Now the thing is, I don’t want to get into the war of mocks vs stubs vs fakes, because frankly… Mocks wins hands down for me (Although if you google this, you’ll find thousands of people that disagree), but I do want to touch on exactly what is the difference between the three. When I talk to developers who are saying “I love fakes, I always use fakes”, and then I start probing them to elaborate, or maybe check their code, what I find is that either they are using stubs/mocks instead, or maybe even a combination of all three. And so hopefully this guide can help you understand what each of these “test doubles” actually are, then you can go onward to your holy war against the one you don’t like against your peers!

What Is A Fake?

A fake is an object used in place of a concrete implementation that has some “smarts” to it. Usually a shortcut implementation that makes it useful across different unit tests, but stops short of being an integration test.

By far the most common example I see of this is in data repositories. Let’s say I have a standard SQL Server repository that looks like so :

public interface IUserRepository
{
    void Insert(object user);
    List<object> GetAllUsers();
}

public class UserRepository : IUserRepository
{
    public List<object> GetAllUsers()
    {
        //Go to the database and fetch all users. 
    }

    public void Insert(object user)
    {
        //Insert a user into the database here. 
    }
}

You’ll have to use your imagination when it comes to the actual implementation part, but essentially we have two methods that call into a database. We have the Insert which adds users, and the GetAllUsers which returns all users in the database.

When it comes to unit testing a class that may utilize IUserRepository, for example a UserService, we have a bit of a problem. We don’t want our unit tests reaching out to the database, and frankly we don’t really care about the implementation of UserRepository. So we create a fake :

public class FakeUserRepository : IUserRepository
{
    private List<object> _users = new List<object>();

    public List<object> GetAllUsers()
    {
        return _users;
    }

    public void Insert(object user)
    {
        _users.Add(user);
    }
}

In our fake, we actually take the inserted user, and add it to an internal list. When GetAllUsers is called, we return that same list. Now whenever a unit test requires a call to IUserRepository, we can supplement in the FakeUserRepository, and instantly things just “work”.

The main thing here is to understand that the Insert affects the GetAllUsers call. It’s a “real” implementation that actually performs like a repository would, just without an actual database behind the scenes.

What Is A Stub?

A stub is an implementation that returns hardcoded responses, but does not have any “smarts” to it. There is no tying together of calls on the object, instead each method just returns a pre-defined canned response.

Let’s look at how we would create a stub for the above :

public class StubOneUserRepository : IUserRepository
{
    public List<object> GetAllUsers()
    {
        return new List<object>();
    }

    public void Insert(object user)
    {
        //Do nothing
    }
}

So it’s somewhat similar to our fake but… Not quite. See how the insert does not affect the GetAllUsers, and the GetAllUsers itself returns a canned response with nothing in it. Anything I do to this object during a test doesn’t change how it functions.

What we generally find is that Stubs are used to fulfil a condition inside the code, but not to test the functionality. For example if my code calls “Insert” on the repository, but I don’t really care about what happens with that data for my particular test, then a stub makes sense rather than the overhead of filling out how a fake would work.

Using a repository makes this example harder than it should be because Repositories invariably should return dynamic data to test various conditions in your code. So let me use another example that would be more likely to require a stub in the real world.

Let’s say I have an interface to tell me if a user is “authenticated” or not. It would look like so :

public interface IUserAuthenticatedCheck
{
    bool IsUserAuthenticated();
}

Now let’s say for my tests, I just always need the user to be authenticated, maybe to fulfil some underlying framework condition. I could use a stub like so :

public class StubUserAuthenticatedCheckTrue : IUserAuthenticatedCheck
{
    public bool IsUserAuthenticated() => true;
}

So no smarts on whether a user should be authenticated, no changing of the value, just a straight “always return true” method. This is what stubs are great at.

What Is A Mock?

A mock is a pre-programmed object that can have dynamic responses/behaviour defined as part of the test. They do not need to be concrete in implementation and (generally) don’t need behaviour to be shared amongst tests.

So where would we use Mocks? Well it’s anywhere you want to be relatively dynamic, for that particular test, to satisfy conditions. As an example, let’s say I am writing a test that calls out to the following interface :

public interface IShopService
{
    bool CheckShopIsOpen(int shopId);
}

So all we are doing is checking if a shop is open or closed. The actual implementation class for this may call out to a database, or a webservice/api of some sort, but we don’t want to do that as part of our unit test.

If we used fakes here, we would need to add some dummy method to be able to say whether a shop should be open or closed. Maybe something like this :

public class FakeShopService : IShopService
{
    public bool ShouldShopBeOpen { get; set; }

    public bool CheckShopIsOpen(int shopId)
    {
        return ShouldShopBeOpen;
    }
}

Eh, not great in my eyes. We are adding new methods just to be able to control whether a shop is open or closed for the test.

If we used stubs, we would have to hardcode a response of true/false right into the concrete class. Maybe even something like this :

public class StubShopService : IShopService
{
    private Dictionary<int, bool> _shops = new Dictionary<int, bool>
    {
        { 1, true },
        { 2, false }
    };

    public bool CheckShopIsOpen(int shopId)
    {
        return _shops[shopId];
    }
}

This works with a predefined list of ids, and whether a shop will be open or closed. It’s nice, but if you use this in a test and pass in the id of 1, it’s not immediately clear from the test why you got the response of true right?

So how would you solve this using mocks? You would write something like this right there in your test (I am using the Moq library for this!) :

var _mockShopService = new Mock<IShopService>();
_mockShopService.Setup(x => x.CheckShopIsOpen(1)).Returns(true);

This is so clear when it’s right there in your test, when our mock is used, and CheckShopIsOpen with an id of 1, then we return true. It’s also specific to this test, and doesn’t force us to hardcode anything anywhere, or create concrete classes.

And when we have a test that requires the shop id of 1 to be false..

_mockShopService.Setup(x => x.CheckShopIsOpen(1)).Returns(false);

Pretty easy stuff!

When To Use Mocks vs Fakes vs Stubs

I know I said I wasn’t going to do this –  I just wanted to explain the differences between the three methods, but.. I feel I have to atleast throw my 2 cents in here on when to use each one. And I’ll let the comments on this post fall as they may!

  • Use Fakes when you want a re-usable concrete implementation that works similar to the real implementation with re-usability across tests (e.g. In Memory Database)
  • Use Stubs when you want a hardcoded response/implementation that will be re-used across tests
  • Use Mocks when you need dynamic responses for individual tests, that may not necessarily require re-usability across tests

If I’m being honest.. I use Mocks even for things like Repositories, it just makes tests for me very readable and very easy to follow when I’m explicitly outlining what’s going to happen. But maybe that’s just me!

For now, hopefully you understand a little better what each of these test doubles are used for and maybe a little more of a nudge on when to use each one.

3 thoughts on “Mocks vs Stubs vs Fakes In Unit Testing”

  1. I would like to add that Test Doubles of any sort (there are more than just these 3*) should be used as sparingly as possible. It should definitely NOT be the case that all classes that the code under test relies on get doubles. That will get you difficult to maintain tests. But most importantly, any use of a Test Double allows the possibility of tests passing and code failing. You are relying on the double to behave like the real code, and if you change behaviour in the real code you have to remember to change all your doubles (of whatever type).
    That alone is why I rarely use mocks, and prefer fakes, myself, as mocks tend to be redeclared all over the place, but I will only have one fake. I generally only use a mock framework when I want to check that an external entity is called correctly.

    *See “xUnit Test Patterns”, Meszaros

    Reply

Leave a Comment