模拟接口在每个 属性 上获得两个幻像调用
Mocked interface gets two phantom invocations on each property
我有一个简单的 class,它向控制台写入一条以当前时间为前缀的消息。它依赖于 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()))
{
}
}
上面的测试失败并显示以下消息:
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
所以我的问题是:额外的调用(界面上每个 属性 两次)来自哪里?
如果我放弃使用 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());
}
这个版本的测试通过了,但我宁愿使用参数来做。
原来我使用的是 Moq
的 4.1.1308.2120 版本,这是目前 AutoFixture.AutoMoq
所需的最低版本,因此也是 Nuget 安装的版本。
将 Moq
更新到最新版本(在此特定情况下为 4.5.28)解决了该问题。
我有一个简单的 class,它向控制台写入一条以当前时间为前缀的消息。它依赖于 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()))
{
}
}
上面的测试失败并显示以下消息:
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
所以我的问题是:额外的调用(界面上每个 属性 两次)来自哪里?
如果我放弃使用 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());
}
这个版本的测试通过了,但我宁愿使用参数来做。
原来我使用的是 Moq
的 4.1.1308.2120 版本,这是目前 AutoFixture.AutoMoq
所需的最低版本,因此也是 Nuget 安装的版本。
将 Moq
更新到最新版本(在此特定情况下为 4.5.28)解决了该问题。