When unit testing, it is common to create a fake implementation of an interface so that you can test another component in isolation. But how do you handle the case where each test needs a fake that does something different?

Here’s an approach that I’ve found quite useful - a fake implementation that allows you to plug in the behaviour needed for the test at hand.

Consider a simple interface for sending messages:

public interface IMessageDispatcher<T>
{
    void SendMessage(T message);
    void PostMessage(T message);
}

Using explicit implementation of the interface, we can create a fake that makes it really easy for consumers to provide their own functionality:

public class FakeMessageDispatcher<T> : IMessageDispatcher<T>
{
    public Action<T> SendMessage { get; set; }
    public Action<T> PostMessage { get; set; }

    void IMessageDispatcher<T>.SendMessage(T message)
        => SendMessage?.Invoke(message);

    void IMessageDispatcher<T>.PostMessage(T message)
        => PostMessage?.Invoke(message);
}

This fake acts as a null implementation if not configured; the writable properties SendMessage and PostMessage allow consumers to provide their own implementation.

For example, here’s a simple test class demonstration.

public class MessengerTests
{
    private readonly FakeMessageDispatcher<string> _dispatcher;
    private readonly Store _store;

    public MessengerTests()
    {
        _dispatcher = new FakeMessageDispatcher<string>();
        _store = new Store(_dispatcher);
    }

    [Fact]
    public void Purchase_GivenProduct_SendsMessage()
    {
        string message = null;
        _dispatcher.SendMessage = m => message = m;

        _store.Purchase("socks");

        message.Should().NotBeNull();
    }
}

Comments

blog comments powered by Disqus
Next Post
Converting a List to a Queue  23 Feb 2019
Prior Post
Capturing Transient Errors  09 Feb 2019
Related Posts
Modifying Words, Part the Second  16 Nov 2019
Modifying Words, Part the First  09 Nov 2019
Hashcodes  26 Oct 2019
Code Gardening  19 Oct 2019
Nullable types redux  12 Oct 2019
C# 8 and .NET Core 3.0  28 Sep 2019
Commands and CommandBinding  21 Sep 2019
Debugging word selection  14 Sep 2019
ViewModel Subscriptions  31 Aug 2019
Redux Subscriptions  25 Aug 2019
More csharp posts »
Archives
February 2019
2019