jeudi 3 décembre 2015

Testing async method does not give consistent result

I am trying to figure out the reason why my unit test would fail when run together with other unit tests in the solution but pass when run alone. Can anyone show me what am I missing?

The SUT is a class called CompositeClient that is essentially a wrapper class around two other clients. It's main idea is to give priority to one of those clients to be called.

public class CompositeClient : IReceiverChannel
{
    private static readonly List<IReceiverChannel> ReceiverChannels = new List<IReceiverChannel>();

    public CompositeClient(IReceiverChannel priority, IReceiverChannel normal)
    {
        ReceiverChannels.Add(priority);
        ReceiverChannels.Add(normal);
    }

    public async Task<IEnumerable<Request>> ReceiveBatchAsync(int batchSize)
    {
        var req = new List<Request>();

        foreach (var channel in ReceiverChannels)
        {
            req.AddRange(await channel.ReceiveBatchAsync(batchSize - req.Count).ConfigureAwait(false));

            if (req.Count >= batchSize)
            {
                break;
            }
        }

        return req;
    }
}

Running the unit test below with all the other unit tests in the solution yield me a failed result. But if I run this test alone, it will pass.

[TestMethod]
public async Task ReceivedRequestShouldComeFromPriorityClientFirst()
{
    var normalPriorityClient = GetNormalClientMock();
    var highPriorityClient = GetPriorityClientMock();
    var compositeClient = new CompositeClient(highPriorityClient, normalPriorityClient);

    var requests = await compositeClient.ReceiveBatchAsync(1);  

    requests.Should().HaveCount(1);
    requests.First().Origin.Should().BeSameAs("priority");

    normalPriorityClient.CallCount.Should().Be(1); // It will fail here with actual CallCount = 0.
    highPriorityClient.CallCount.Should().Be(0);
}

private static ReceiverChannelMock GetNormalClientMock()
{
    return new ReceiverChannelMock("normal");
}

private static ReceiverChannelMock GetPriorityClientMock()
{
    return new ReceiverChannelMock("priority");
}

private class ReceiverChannelMock : IReceiverChannel
{
    private readonly string name;

    public ReceiverChannelMock(string name)
    {
        this.name = name;
    }

    public int CallCount { get; private set; }

    public Task<IEnumerable<Request>> ReceiveBatchAsync(int batchSize)
    {
        this.CallCount++;
        return Task.FromResult<IEnumerable<Request>>(
            new List<Request>
                            {
                                new Request
                                    {
                                        Origin = this.name
                                    }
                            });
    }
}

Tools used:

  • Visual Studio 2013
  • .NET Framework 4.5.2
  • Resharper 9.2
  • FluentAssertion

Aucun commentaire:

Enregistrer un commentaire