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

发布于 2024-12-04 17:29:28 字数 2054 浏览 0 评论 0原文

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

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; }    
}

,以下是特定的存储库

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:参数计数不匹配

不知道为什么?

Following is my generic base repository interface

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

my entity

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

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

    public string Identifier { get; set; }    
}

and following is the specific repo

public interface ISdkRepository : IRepository<Sdk>
{
}

now I am trying to test a controller, using moq

Following is the code I am trying to test

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());
    }

using following test

[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();
}

and it is throwing:

System.Reflection.TargetParameterCountException : Parameter count mismatch

Don't know why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

寄居人 2024-12-11 17:29:28

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

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());

Though there is an answer marked as accepted, I believe there is a way to mock your repository correctly.

Instead of

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

please use

mockRepo.Setup(k => k.AllIncluding(It.IsAny<Expression<Func<Sdk, object>>[]>()))
                     .Returns((Expression<Func<Sdk, 
                        object>>[] includeProperties) => sdks.AsQueryable());
掩饰不了的爱 2024-12-11 17:29:28

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

Another solution for solving this issue is to use: .AsQueryable() instead of .AsQueryable.

·深蓝 2024-12-11 17:29:28

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

另外,我不记得 Moq 处理参数 xx[] 的效果如何,但很可能这里同时存在两个问题。

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

更新

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

I think you've hit some limitations here with Moq. It doesn't handle expression parameters well because it can be passed expressions as values itself. There's no way for Moq to know what part of the expression is intended to be resolved and what is part of the signature.

Also, I can't remember how well Moq handles params xx[] but it's quite possible you have a combination of two problems here.

Are you able to create a class that exposes the set of expressions as a property? If so it might be possible to change the signature of AllIncluding and tell Moq to match on any instance of that class.

Update

At the time of answering this was a limitation but is now possible. See the answer by Oleksandr Lytvyn

花落人断肠 2024-12-11 17:29:28

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

例如:

不使用不同的参数数量

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

Returns 中的表达式中使用与 Setup< 中相同数量的参数/代码>

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

For other people looking for answer to this the solution for me was adding the same number of parameters in Setup as in the expression in Returns.

For example:

Not working with different argument count

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

Working with same amount of args in expression in Returns as in Setup

mock.Setup(x => x.DoSomething(It.IsAny<string>()))
                .Returns((string s1, string s2) => s1.ToLower());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文