Moq链表达式导致参数计数不匹配

时间:2014-07-13 02:29:10

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

我试图使用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;
    }

每当我尝试在我的测试中使用模拟存储库运行此服务方法时,它会抛出异常&#34; System.Reflection.TargetParameterCountException:参数计数不匹配。&#34;

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

由于Include()和Query()方法返回一个IQueryFluent()实例而不是直接表达式,我试图在Moq return()方法中使用QueryFluent()类但是还没有能够做到它成功地使用了queryable(编译错误)。

非常感谢任何帮助,真的希望能够使用单元测试来正确测试。

编辑 - 我所看过的类似问题

1 个答案:

答案 0 :(得分:2)

问题在于这一行:

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

你不能(就我的Moq知识而言)在一次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));

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