2016-12-21 14 views
1

У меня есть простой класс, который записывает сообщение в консоль с префиксом текущего времени. Он имеет зависимость от интерфейса IDateTimeProvider как абстракции над 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}"); 
    } 
} 

Для того, чтобы проверить, что метод Write называет IDateTimeProvider.Now я написал следующий тест с использованием XUnit, AutoFixture и 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()); 
    } 
} 

Я использую AutoMoqDataAttribute, как видно на http://blog.ploeh.dk/2010/10/08/AutoDataTheorieswithAutoFixture/

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

T он выше тест терпит неудачу со следующим сообщением:

ожидаемый вызов на издеваться один раз, но в 3 раза: м => m.Now

Нет сконфигурированных настроек.

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 

Так что мой вопрос: откуда берутся дополнительные вызовы (два для каждого свойства на границе раздела) пришли?

Если я воздержусь с помощью AutoMoqDataAttribute этой проблемы уходит:

[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()); 
    } 

Этой версия теста проходит, но я предпочел бы сделать это с помощью параметров.

ответ

1

Оказывается, я использовал версию 4.1.1308.2120 из Moq, ту самую, которая в настоящее время является самой низкой версией, требуемой AutoFixture.AutoMoq и, следовательно, версией, которая была установлена ​​Nuget.

Обновление Moq до последней версии (4.5.28 в данном конкретном случае) устраняет проблему.