【问题标题】:Moq chaining expressions results in parameter count mismatchMoq 链接表达式导致参数计数不匹配
【发布时间】:2014-09-03 08:05:07
【问题描述】:

我正在尝试使用 Moq 模拟存储库。我发现了多个具有类似问题的问题,但我发现没有一个能够解决我遇到的问题。

所以我正在使用可以下载的存储库here。更具体地说,可以查看存储库本身 here 并且可以查看我正在使用的查询扩展 here

这是我的测试设置的样子:

        // A List<> of fakes.
        this.containers = Builder<Container>.CreateListOfSize(10).Build();

        // Here I'm trying to set up the mock object for the query.
        this.containerRepoMock.Setup(p => p.
            Query(It.IsAny<Expression<Func<Container, bool>>>())
                .Include(It.IsAny<Expression<Func<Container, object>>>())
                .Select())
            .Returns((Expression<Func<Container, bool>> query, Expression<Func<Container, object>> include) => 
                 this.containers.AsQueryable().Where(query).Include(include));

        // Tell the service to use the mock repository.
        this.containerService = new ContainerService(mockUnitOfWork.Object);

这是我要测试的服务方法:

    public ContainerDto GetContainerAndItsCategories(int containerId)
    {
        var entity = Repository
            .Query(w => w.ContainerId == containerId)
            .Include(c => c.Categories)
            .Select();

        var output = Mapper.EntityToDto(entity.SingleOrDefault());

        return output;
    }

每当我尝试使用模拟存储库在我的测试中运行此服务方法时,它都会引发异常“System.Reflection.TargetParameterCountException:参数计数不匹配。”

我尝试在模拟设置中向 .Returns() 方法添加额外的对象参数,但没有成功。它总是抛出相同的异常。从我一直在阅读的内容来看,在测试表达式方面,起订量有些有限,但是我看到了人们成功地做类似事情的例子。

由于 Include() 和 Query() 方法返回 IQueryFluent() 实例而不是直接表达式,我尝试在 Moq return() 方法中使用 QueryFluent() 类,但未能成功带有可查询(编译错误)。

任何帮助将不胜感激,真的希望能够使用单元测试正确测试。

编辑 - 我看过的类似问题

【问题讨论】:

  • 虽然写得很好,但你的问题需要我做大量的工作才能归结为问题陈述。下次尝试创建一个更好的SSCCE,以便更快地得到答案。
  • 我试图让它变得简单,但也试图包含可能相关的信息。猜猜我做得过火了。感谢您不厌其烦地调查它。今天晚些时候我会试试你的解决方案。
  • 不用担心,它完成了工作。祝你好运!

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


【解决方案1】:

问题在于这一行:

this.containerRepoMock.Setup(p => p.
        Query(It.IsAny<Expression<Func<Container, bool>>>())
        .Include(It.IsAny<Expression<Func<Container, object>>>())
        .Select())

您不能(就我的起订量知识而言)在一个 Setup 调用中设置一组方法。此外,在这一行中:

.Returns((Expression<Func<Container, bool>> query, Expression<Func<Container, object>> include) => 
    this.containers.AsQueryable().Where(query).Include(include));

您告诉 Moq 期望(在 Setup 调用中)调用具有两个参数(queryinclude)的单个方法,并将它们传递给此处的 Returns lambda。显然情况并非如此:您调用了两个单参数方法,因此 Moq 会引发参数不匹配异常。

您需要将其分解为其组件并为返回值设置模拟。此外,由于您想使用 Expression 对象,您需要将它们保存起来以备最后使用。例如:

var containerRepoMock = new Mock<IRepositoryAsync<Container>>();
var queryFluentQueryMock = new Mock<IQueryFluent<Container>>();
var queryFluentIncludeMock = new Mock<IQueryFluent<Container>>();

Expression<Func<Container, bool>> query = null;
containerRepoMock.Setup(p => p.Query(It.IsAny<Expression<Func<Container, bool>>>()))
                 .Callback<Expression<Func<Container, bool>>>(q => query = q)
                 .Returns(queryFluentQueryMock.Object);

Expression<Func<Container, object>> include = null;
queryFluentQueryMock.Setup(p => p.Include(It.IsAny<Expression<Func<Container, object>>>()))
                    .Callback<Expression<Func<Container, object>>>(i => include = i)
                    .Returns(queryFluentIncludeMock.Object);

queryFluentIncludeMock.Setup(p => p.Select())
                 .Returns(containers.AsQueryable().Where(query).Include(include));

请原谅任何编译错误,我没有下载你链接到的库来试试这个

【讨论】:

  • 测试运行,但要做到这一点,我必须在定义表达式时设置表达式(否则会出现编译器错误“局部变量在访问之前可能未初始化”)。因此 containerRepoMock 和 queryFluentQueryMock 上的 Setup() 似乎无法正确运行。至少他们没有取代预设的表达方式。知道可能缺少什么吗?
  • 在我的脑海中,不,我不明白他们为什么不工作。不幸的是,我将无法在几周内进行调试。如果你弄明白了,请回来评论!
猜你喜欢
  • 2016-09-21
  • 2011-11-17
  • 1970-01-01
  • 2011-12-04
  • 1970-01-01
  • 2019-08-07
  • 1970-01-01
  • 1970-01-01
  • 2012-01-20
相关资源
最近更新 更多