Mocked interface gets two phantom invocations on each property

158 views Asked by At

I have a simple class that writes a message to the Console prefixed with the current time. It has a dependency on an IDateTimeProvider interface as an abstraction over DateTime.Now

public interface IDateTimeProvider
{
    DateTime Now { get; }
    DateTime UtcNow { get; }
}

public class MessageWriter
{
    private readonly IDateTimeProvider _dateTimeProvider;

    public MessageWriter(IDateTimeProvider dateTimeProvider)
    {
        _dateTimeProvider = dateTimeProvider;
    }

    public void Write(string message)
    {
        Console.WriteLine($"{_dateTimeProvider.Now.ToShortTimeString()} : {message}");
    }
}

In order to test that the Write method calls IDateTimeProvider.Now I've written the following test using xUnit, AutoFixture and Moq:

public class MessageWriterTests
{
    [Theory, AutoMoqData]
    public void Write_Always_CallsDateTimeProvider(
        [Frozen] Mock<IDateTimeProvider> dateTimeProviderMock,
        MessageWriter sut,
        string message)
    {
        sut.Write(message);

        dateTimeProviderMock.Verify(m => m.Now, Times.Once());
    }
}

I'm using AutoMoqDataAttribute as seen on http://blog.ploeh.dk/2010/10/08/AutoDataTheorieswithAutoFixture/

public class AutoMoqDataAttribute : AutoDataAttribute
{
    public AutoMoqDataAttribute()
        : base(new Fixture()
            .Customize(new AutoMoqCustomization()))
    {
    }
}

The test above fails with the following message:

Expected invocation on the mock once, but was 3 times: m => m.Now

No setups configured.

Performed invocations:
IDateTimeProvider.Now
IDateTimeProvider.UtcNow
IDateTimeProvider.Now
IDateTimeProvider.UtcNow
IDateTimeProvider.Now
   at Moq.Mock.ThrowVerifyException(MethodCall expected, IEnumerable`1 setups,  IEnumerable`1 actualCalls, Expression expression, Times times, Int32 callCount)
   at Moq.Mock.VerifyCalls(Interceptor targetInterceptor, MethodCall expected, Expression expression, Times times)
   at Moq.Mock.VerifyGet[T,TProperty](Mock`1 mock, Expression`1 expression, Times times, String failMessage)
   at Moq.Mock.Verify[T,TResult](Mock`1 mock, Expression`1 expression, Times times, String failMessage)
   at Moq.Mock`1.Verify[TResult](Expression`1 expression, Times times)
   at MoqBug.Tests.MessageWriterTests.Write_Always_CallsDateTimeProvider(Mock`1 dateTimeProviderMock, MessageWriter sut, String message) in c:\Users\rik van der sanden\documents\visual studio 2015\Projects\MoqBug\MoqBug.Tests\MessageWriterTests.cs:line 21

So my question is: where do the extra invocations (two for each property on the interface) come from?

If I forego using the AutoMoqDataAttribute the problem goes away:

    [Theory, AutoData]
    public void Write_Always_CallsDateTimeProvider(
        string message)
    {
        IFixture fixture = new Fixture().Customize(new AutoMoqCustomization());
        Mock<IDateTimeProvider> dateTimeProviderMock = fixture.Freeze<Mock<IDateTimeProvider>>();
        MessageWriter sut = fixture.Create<MessageWriter>();

        sut.Write(message);

        dateTimeProviderMock.Verify(m => m.Now, Times.Once());
    }

This version of the test passes, but I'd rather do it using the parameters.

1

There are 1 answers

0
Rik On BEST ANSWER

Turns out I was using version 4.1.1308.2120 of Moq, that one that's currently the lowest version required by AutoFixture.AutoMoq and hence the version that got installed by Nuget.

Updating Moq to the latest version (4.5.28 in this particular case) fixed the problem.