Moq Params TargetParameterCountException:参数计数不匹配异常

Ama*_*anT 11 .net c# unit-testing moq mocking

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

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

我的实体

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

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

    public string Identifier { get; set; }    
}
Run Code Online (Sandbox Code Playgroud)

以下是具体的回购

public interface ISdkRepository : IRepository<Sdk>
{
}
Run Code Online (Sandbox Code Playgroud)

现在我正在尝试使用moq测试控制器

以下是我试图测试的代码

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());
    }
Run Code Online (Sandbox Code Playgroud)

使用以下测试

[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();
}
Run Code Online (Sandbox Code Playgroud)

它投掷:

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

不知道为什么?

小智 29

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

代替

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

请用

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


小智 8

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


JRo*_*han 5

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

另外,我不记得Moq如何处理params xx []但是你很可能在这里遇到两个问题的组合.

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

更新

在回答时,这是一个限制,但现在是可能的.请参阅Oleksandr Lytvyn的回答