Moq 验证方法签名看到调用但不匹配?
Moq verify method signature sees invocations but doesn't match on them?
我有这样的界面:
public interface IStatisticsCollector : IDisposable
{
Task Measure(string metricName, decimal value, IDictionary<string, string> tags = null);
}
我正在将这个 IStatisticsCollector
注入我的 class 并像这样使用它:
var stopwatch = new Stopwatch();
await dataCollector.Measure("rbk_init", stopwatch.ElapsedMilliseconds);
...
await dataCollector.Measure("rbk_compiled", stopwatch.ElapsedMilliseconds);
...
设置我的单元测试以验证我正在记录我想要的所有统计点,我模拟 IStatisticsCollector
:
private readonly Mock<IStatisticsCollector> _statisticsCollector = new Mock<IStatisticsCollector>();
_statisticsCollector.Setup(x => x.Measure(It.IsAny<string>(), It.IsAny<long>(), It.IsAny<IDictionary<string, string>>())).Verifiable();
当我 运行 我的单元测试时,我在这一行验证失败:
//assert
_statisticsCollector.Verify(
x => x.Measure(It.IsAny<string>(), It.IsAny<long>(), It.IsAny<IDictionary<string, string>>()), Times.Exactly(5));
...带有以下消息:
Moq.MockException :
Expected invocation on the mock exactly 5 times, but was 0 times: x => x.Measure(It.IsAny<string>(), (decimal)It.IsAny<long>(), It.IsAny<IDictionary<string, string>>())
Configured setups:
IStatisticsCollector x => x.Measure(It.IsAny<string>(), (decimal)It.IsAny<long>(), It.IsAny<IDictionary<string, string>>())
Performed invocations:
IStatisticsCollector.Measure("rbk_init", 31, null)
IStatisticsCollector.Measure("rbk_compiled", 35, null)
IStatisticsCollector.Measure("rbk_stored", 36, null)
IStatisticsCollector.Measure("rbk_db_updated", 352, null)
IStatisticsCollector.Measure("rbk_completed", 361, null)
at Moq.Mock.VerifyCalls(Mock targetMock, InvocationShape expectation, LambdaExpression expression, Times times, String failMessage) in C:\projects\moq4\src\Moq\Mock.cs:line 378
...这很奇怪,因为看起来它捕获了 5 个匹配的调用,但显然没有将它们中的任何一个视为实际匹配。现在我假设这可能与秒表的 ElapsedMilliseconds
很长但界面需要小数(带有隐式转换)这一事实有关,所以我更改了验证以查找 It.IsAny<decimal>()
,但是这让我得到了意想不到的结果:
Moq.MockException :
Expected invocation on the mock exactly 5 times, but was 1 times: x => x.Measure(It.IsAny<string>(), It.IsAny<decimal>(), It.IsAny<IDictionary<string, string>>())
Configured setups:
IStatisticsCollector x => x.Measure(It.IsAny<string>(), It.IsAny<decimal>(), It.IsAny<IDictionary<string, string>>())
Performed invocations:
IStatisticsCollector.Measure("rbk_init", 28, null)
at Moq.Mock.VerifyCalls(Mock targetMock, InvocationShape expectation, LambdaExpression expression, Times times, String failMessage) in C:\projects\moq4\src\Moq\Mock.cs:line 378
找到了一个……而且只有一个。好像没有抛出异常,不知道为什么只有一个。
我还注意到可选参数上的空值,并尝试根据空值而不是 IDictionary<string, string>
进行验证,但这同样没有结果。
有人可以解释这种行为吗?我需要做什么来修复我的测试?
这一行总是失败:
_statisticsCollector.Verify(
x => x.Measure(It.IsAny<string>(), It.IsAny<long>(), It.IsAny<IDictionary<string, string>>()), Times.Exactly(5));
发生这种情况是因为您对模拟说它需要在第二个参数中接收一个 long,但是接口说在第二个参数中它将接收一个小数:
public interface IStatisticsCollector : IDisposable
{
Task Measure(string metricName, decimal value, IDictionary<string, string> tags = null);
}
因为小数不能太长,所以你的验证总是失败。
我有这样的界面:
public interface IStatisticsCollector : IDisposable
{
Task Measure(string metricName, decimal value, IDictionary<string, string> tags = null);
}
我正在将这个 IStatisticsCollector
注入我的 class 并像这样使用它:
var stopwatch = new Stopwatch();
await dataCollector.Measure("rbk_init", stopwatch.ElapsedMilliseconds);
...
await dataCollector.Measure("rbk_compiled", stopwatch.ElapsedMilliseconds);
...
设置我的单元测试以验证我正在记录我想要的所有统计点,我模拟 IStatisticsCollector
:
private readonly Mock<IStatisticsCollector> _statisticsCollector = new Mock<IStatisticsCollector>();
_statisticsCollector.Setup(x => x.Measure(It.IsAny<string>(), It.IsAny<long>(), It.IsAny<IDictionary<string, string>>())).Verifiable();
当我 运行 我的单元测试时,我在这一行验证失败:
//assert
_statisticsCollector.Verify(
x => x.Measure(It.IsAny<string>(), It.IsAny<long>(), It.IsAny<IDictionary<string, string>>()), Times.Exactly(5));
...带有以下消息:
Moq.MockException :
Expected invocation on the mock exactly 5 times, but was 0 times: x => x.Measure(It.IsAny<string>(), (decimal)It.IsAny<long>(), It.IsAny<IDictionary<string, string>>())
Configured setups:
IStatisticsCollector x => x.Measure(It.IsAny<string>(), (decimal)It.IsAny<long>(), It.IsAny<IDictionary<string, string>>())
Performed invocations:
IStatisticsCollector.Measure("rbk_init", 31, null)
IStatisticsCollector.Measure("rbk_compiled", 35, null)
IStatisticsCollector.Measure("rbk_stored", 36, null)
IStatisticsCollector.Measure("rbk_db_updated", 352, null)
IStatisticsCollector.Measure("rbk_completed", 361, null)
at Moq.Mock.VerifyCalls(Mock targetMock, InvocationShape expectation, LambdaExpression expression, Times times, String failMessage) in C:\projects\moq4\src\Moq\Mock.cs:line 378
...这很奇怪,因为看起来它捕获了 5 个匹配的调用,但显然没有将它们中的任何一个视为实际匹配。现在我假设这可能与秒表的 ElapsedMilliseconds
很长但界面需要小数(带有隐式转换)这一事实有关,所以我更改了验证以查找 It.IsAny<decimal>()
,但是这让我得到了意想不到的结果:
Moq.MockException :
Expected invocation on the mock exactly 5 times, but was 1 times: x => x.Measure(It.IsAny<string>(), It.IsAny<decimal>(), It.IsAny<IDictionary<string, string>>())
Configured setups:
IStatisticsCollector x => x.Measure(It.IsAny<string>(), It.IsAny<decimal>(), It.IsAny<IDictionary<string, string>>())
Performed invocations:
IStatisticsCollector.Measure("rbk_init", 28, null)
at Moq.Mock.VerifyCalls(Mock targetMock, InvocationShape expectation, LambdaExpression expression, Times times, String failMessage) in C:\projects\moq4\src\Moq\Mock.cs:line 378
找到了一个……而且只有一个。好像没有抛出异常,不知道为什么只有一个。
我还注意到可选参数上的空值,并尝试根据空值而不是 IDictionary<string, string>
进行验证,但这同样没有结果。
有人可以解释这种行为吗?我需要做什么来修复我的测试?
这一行总是失败:
_statisticsCollector.Verify(
x => x.Measure(It.IsAny<string>(), It.IsAny<long>(), It.IsAny<IDictionary<string, string>>()), Times.Exactly(5));
发生这种情况是因为您对模拟说它需要在第二个参数中接收一个 long,但是接口说在第二个参数中它将接收一个小数:
public interface IStatisticsCollector : IDisposable
{
Task Measure(string metricName, decimal value, IDictionary<string, string> tags = null);
}
因为小数不能太长,所以你的验证总是失败。