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
Debugging word selection  14 Sep 2019
ViewModel Subscriptions  31 Aug 2019
Redux Subscriptions  25 Aug 2019
Dependency Injection: Views  17 Aug 2019
Dependency Injection: ViewModels  10 Aug 2019
Dependency Injection: Core  27 Jul 2019
Integration Testing  20 Jul 2019
Restructuring Reducers  13 Jul 2019
Vocabulary Browser  29 Jun 2019
Revisiting ViewModelBase  15 Jun 2019
More csharp posts »
Archives
February 2019
2019