【问题标题】:Parameter count mismatch in a Mocked method call模拟方法调用中的参数计数不匹配
【发布时间】:2015-01-10 11:17:50
【问题描述】:

我有这个方法:

public void Valida(Validazione.IValidator<MyType> validator)
{
    // do something...
    Validazione.IMapper<MyType> mapper = new MyTypeMapper();
    ValidationResult result = validator.Validate(myTypeObj, mapper, new ValidationConfiguration());
    // ...continue doing something else
}

我想进行单元测试,所以我会模拟(使用 Moq 框架)validator 来引导Validate 方法的结果,所以我编写了这个单元测试:

[TestMethod]
public void Long_test_name_as_best_practice()
{
    // arrange
    MyAggregateRoot aggregateRoot = AggregateRoot.Stub();
    var mockedValidator = new Mock<Validazione.IValidator<MyType>>();

    mockedValidator.Setup(a => a.Validate(
        It.Is<MyType>(x => x.Id == Guid.Parse("3F2504E0-4F89-11D3-9A0C-0305E82C3301")),
        It.IsAny<Validazione.IMapper<MyType>>(), 
        It.IsAny<ValidationConfiguration>()
    )).Returns<Validazione.ValidationResult>(x => x = It.IsAny<Validazione.ValidationResult>());

    // act
    aggregateRoot.Valida(mockedValidator.Object);

    // Assert (now showed for readability sake)
}

它构建了,听起来我很正确,但最后我得到了:

“System.Reflection.TargetParameterCountException”类型的异常 发生在 mscorlib.dll 中但未在用户代码中处理 附加信息:参数计数不匹配

我四处搜索,但我无法理解原因。在我看来还可以。

评论后编辑

这是异常的堆栈跟踪:

   in System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   in System.Reflection.RuntimeMethodInfo.UnsafeInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   in System.Delegate.DynamicInvokeImpl(Object[] args)
   in System.Delegate.DynamicInvoke(Object[] args)
   in Moq.Extensions.InvokePreserveStack(Delegate del, Object[] args)
   in Moq.MethodCallReturn`2.Execute(ICallContext call)
   in Moq.ExecuteCall.HandleIntercept(ICallContext invocation, InterceptorContext ctx, CurrentInterceptContext localctx)
   in Moq.Interceptor.Intercept(ICallContext invocation)
   in Moq.Proxy.CastleProxyFactory.Interceptor.Intercept(IInvocation invocation)
   in Castle.DynamicProxy.AbstractInvocation.Proceed()
   in Castle.Proxies.IValidator`1Proxy.Validate(MyType myTypeObj, IMapper`1 mapper, ValidationConfiguration configuration)
   in MyNamespace.Valida(IValidator`1 validator) in c:\Sviluppo\ProjectName\Main\src\Project.MySubProject.Domain\filename.cs:riga 104
   in MyTestNamespace.Long_test_name_as_best_practice() in c:\Sviluppo\ProjectName\Main\src\Project.SubProject.Domain.Tests\Test_AggregateCommand.cs:riga 103

【问题讨论】:

  • 异常的调用栈是什么?不清楚是你的测试代码还是你的生产代码有问题。
  • 查看更新问题。 ;)

标签: unit-testing testing mocking automated-tests moq


【解决方案1】:

在此Setup 语句的Returns 子句中:

mockedValidator.Setup(a => a.Validate(
    It.Is<MyType>(x => x.Id == Guid.Parse("3F2504E0-4F89-11D3-9A0C-0305E82C3301")),
    It.IsAny<Validazione.IMapper<MyType>>(), 
    It.IsAny<ValidationConfiguration>()
)).Returns<Validazione.ValidationResult>(x => x = It.IsAny<Validazione.ValidationResult>());

看起来你并不关心这个方法返回什么。但是你给Returns 声明一个Func&lt;ValidationResult.ValidationResult&gt;。这就是您的异常的来源。

此语法旨在允许您根据正在设置的方法的输入来计算返回值(这里是 Validate),因此您应该传入带有相同参数的 Func正在设置的方法。由于您的方法有 3 个参数,并且您给 Returns 一个接受 1 的函数,因此存在参数不匹配。

如果您只想返回任何 ValidationResult,请改为:

.Returns(It.IsAny<Validazione.ValidationResult>())

如果您确实想根据 Validate 的参数计算 ValidationResult,请执行以下操作:

.Returns<MyType, Validazione.IMapper<MyType>, ValidationConfiguration>
    ((m,t,c) => /* TODO: compute a ValidationResult */ )

【讨论】:

  • 你就是那个男人! ;) 感谢您的支持,即使我找不到关于 Moq 框架的有用文档。
  • 没问题。 Moq Quickstart 是最好的去处,并在示例下通过注释“返回值时访问调用参数” 提到了这种用法。也有API docs,不过老实说我完全没用过。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-01
  • 1970-01-01
  • 2020-04-19
相关资源
最近更新 更多