【问题标题】:Moq Params TargetParameterCountException : Parameter count mismatch ExceptionMoq Params TargetParameterCountException:参数计数不匹配异常
【发布时间】:2011-11-17 05:26:46
【问题描述】:

以下是我的通用基础存储库接口

public interface IRepository<T>
{
    IQueryable<T> AllIncluding(params Expression<Func<T, 
                               object>>[] includeProperties);
}

我的实体

public class Sdk 
{
    public Sdk()
    {
       this.Identifier = Guid.NewGuid().ToString();
    }

    public virtual ICollection<Resource> AccessibleResources { get; set; }

    public string Identifier { get; set; }    
}

以下是具体的repo

public interface ISdkRepository : IRepository<Sdk>
{
}

现在我正在尝试使用最小起订量测试控制器

以下是我要测试的代码

public ActionResult GetResources(string clientId) {
        var sdkObject = sdkRepository
                           .AllIncluding(k => k.AccessibleResources)
                           .SingleOrDefault(k => k.Identifier == clientId);
        if (sdkObject == null)
            throw new ApplicationException("Sdk Not Found");
        return Json(sdkObject.AccessibleResources.ToList());
    }

使用以下测试

[Test]
public void Can_Get_GetResources()
{
    var cid = Guid.NewGuid().ToString();
    var mockRepo = new Moq.Mock<ISdkRepository>();
    var sdks = new HashSet<Sdk>()
    {
        new Sdk()
        {
            Identifier = cid,
            AccessibleResources = new HashSet<Resource>()
            {
                new Resource()
                {
                    Id = Guid.NewGuid(),
                    Description = "This is sdk"
                }
            }
        }
    };
    mockRepo.Setup(k => k.
        AllIncluding(It.IsAny<Expression<Func<Sdk,object>>[]>()))
                       .Returns(sdks.AsQueryable);
    var sdkCtrl = new SdksController(mockRepo.Object);
    var returnedJson=sdkCtrl.GetResources(cid);
    returnedJson.ToString();
}

它正在抛出:

System.Reflection.TargetParameterCountException : 参数计数不匹配

不知道为什么?

【问题讨论】:

  • 你能粘贴堆栈跟踪吗?

标签: c# .net unit-testing mocking moq


【解决方案1】:

对于寻找此问题答案的其他人,我的解决方案是在 Setup 中添加与 Returns 中的表达式相同数量的参数。

例如:

不适用于不同的参数计数

mock.Setup(x => x.DoSomething(It.IsAny<string>(), It.IsAny<string>()))
                .Returns((string s) => s.ToLower());

Returns 中的表达式中使用与 Setup 中相同数量的 args

mock.Setup(x => x.DoSomething(It.IsAny<string>()))
                .Returns((string s1, string s2) => s1.ToLower());

【讨论】:

    【解决方案2】:

    我认为您在使用 Moq 时遇到了一些限制。它不能很好地处理表达式参数,因为它可以将表达式作为值本身传递。 Moq 无法知道要解析表达式的哪一部分以及签名的哪一部分。

    另外,我不记得 Moq 处理参数 xx[] 的能力如何,但很可能您在这里遇到了两个问题。

    您是否能够创建一个将表达式集公开为属性的类?如果是这样,则可以更改 AllIncluding 的签名并告诉 Moq 匹配该类的任何实例。

    更新

    在回答时这是一个限制,但现在可以了。查看 Oleksandr Lytvyn 的答案

    【讨论】:

    • 请查看 Oleksandr Lytvyn 的答案。
    【解决方案3】:

    解决此问题的另一种解决方案是使用:.AsQueryable() 而不是 .AsQueryable

    【讨论】:

      【解决方案4】:

      虽然有一个标记为已接受的答案,但我相信有一种方法可以正确地模拟您的存储库。

      代替

      mockRepo.Setup(k => k.AllIncluding(It.IsAny<Expression<Func<Sdk, object>>[]>()))
                           .Returns(sdks.AsQueryable);
      

      请使用

      mockRepo.Setup(k => k.AllIncluding(It.IsAny<Expression<Func<Sdk, object>>[]>()))
                           .Returns((Expression<Func<Sdk, 
                              object>>[] includeProperties) => sdks.AsQueryable());
      

      【讨论】:

      • 它拯救了我的一天)我以完全相同的方法遇到了完全相同的问题,您的建议有效!
      • 谢谢!救了我
      • 太棒了!工作。有没有解释它是如何工作的(这实际上是做什么的)?
      • @Marcel 之所以能正常工作,是因为您告诉 Moq AllIncluding 需要(通过It.IsAny&lt;TExpected&gt;)一个参数,但sdks.AsQueryable() 是一种(n 扩展)方法没有任何参数。由于您可以只使用方法名称作为委托的简写,它可以让您编译它,但在 Moq 评估它时会失败。给它一个显式委托返回评估的.AsQueryable 然后符合预期的模式。
      猜你喜欢
      • 2017-12-31
      • 2016-09-21
      • 1970-01-01
      • 2011-12-04
      • 1970-01-01
      • 2018-02-14
      • 2019-08-07
      • 2014-09-03
      • 1970-01-01
      相关资源
      最近更新 更多