Moq'ing方法,其中前pression<&Func键LT; T,BOOL>>被作为参数传入 [英] Moq'ing methods where Expression<Func<T, bool>> are passed in as parameters

查看:95
本文介绍了Moq'ing方法,其中前pression<&Func键LT; T,BOOL>>被作为参数传入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很新的单元测试和嘲弄!我试着写一些单元测试,涵盖一些code,与数据存储交互。数据访问是通过IRepository封装:

I'm very new to unit testing and mocking! I'm trying to write some unit tests that covers some code that interacts with a data store. Data access is encapsulated by IRepository:

interface IRepository<T> {
    ....
    IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate);
    ....
}

这是我试图测试,利用一个具体的实施IoC'd的IRepository的code是这样的:

The code that I'm trying to test, utilising a concrete IoC'd implementation of IRepository looks like this:

public class SignupLogic {
    private Repository<Company> repo = new Repository<Company>();

    public void AddNewCompany(Company toAdd) {
        Company existingCompany = this.repo.FindBy(c => c.Name == toAdd.Name).FirstOrDefault();

        if(existingCompany != null) {
            throw new ArgumentException("Company already exists");
        }

        repo.Add(Company);
        repo.Save();
    }
}

让我测试)SignupLogic.AddNewCompany的逻辑(本身,而不是逻辑和具体的存储库,我嘲笑起来IRepository并将它传递到SignupLogic。嘲笑了库看起来是这样的:

So that I'm testing the logic of SignupLogic.AddNewCompany() itself, rather than the logic and the concrete Repository, I'm mocking up IRepository and passing it into SignupLogic. The mocked up Repository looks like this:

Mock<Repository> repoMock = new Mock<Repository>();
repoMock.Setup(moq => moq.FindBy(c => c.Name == "Company Inc")....

返回一个内存中含有名称设置为本公司公司公司对象IEnumberable。调用SignupLogic.AddNewCompany建立一家具有重复的细节,改掉单元测试通过,在和我断言将引发ArgumentException消息公司已经存在。这个测试不及格。

which returns an in-memory IEnumberable containing a Company object with name set to "Company Inc". The unit test that calls SignupLogic.AddNewCompany sets up a company with duplicate details and trys to pass that in, and I assert that an ArgumentException is thrown with the message "Company already exists". This test isn't passing.

通过单元测试和调试AddNewCompany(),因为它运行时,它会出现existingCompany总是空。无奈之下,我发现,如果我更新SignupLogic.AddNewCompany(),以便调用FindBy看起来是这样的:

Debugging through the unit test and AddNewCompany() as it runs, it would appear that existingCompany is always null. In desperation, I've found that if I update SignupLogic.AddNewCompany() so that the call to FindBy looks like this:

Company existingCompany = this.repo.FindBy(c => c.Name == "Company Inc").FirstOrDefault();

测试通过,这表明对我来说,起订量只响应code是的究竟的为我设置在我的测试夹具相同。显然,这不是在测试中,任何重复的公司是由SignupLogic.AddNewCompany拒绝特别有用。

the test passes, which suggests to me that Moq is only responding to code that is exactly the same as I've setup in my test fixture. Obviously that's not especially useful in testing that any duplicate company is rejected by SignupLogic.AddNewCompany.

我试过设置moq.FindBy(...)用Is.ItAny,但是,这并不导致测试要么通过。

I've tried setting up moq.FindBy(...) to use "Is.ItAny", but that doesn't cause the test to pass either.

这一切我读,它会出现测试前pressions因为我想是不是真正做到,能够与这里起订量。是否可以?请帮助!

From everything I'm reading, it would appear that testing Expressions as I'm trying to isn't actually do-able with Moq here. Is it possible? Please help!

推荐答案

有可能是正确的,只有一个防爆pression 用完全相同的结构(和文字值),将匹配。我建议你​​使用返回(),让您使用模拟被调用的参数过载:

It is probably correct that only an Expression with the exactly same structure (and literal values) will match. I suggest that you use the overload of Returns() that lets you use the parameters the mock is called with:

repoMock.Setup(moq => moq.FindBy(It.IsAny<Expression<Func<Company, bool>>>())
        .Returns((Expression<Func<Company, bool>> predicate) => ...);

... ,您可以使用 predicate 来返回匹配的公司(甚至可能如果匹配的公司是不是你所期望的)抛出异常。不是很pretty,但我认为它会工作。

In ..., you can use predicate to return the matching companies (and maybe even throw an exception if the matching companies isn't what you expected). Not very pretty, but I think it will work.

这篇关于Moq'ing方法,其中前pression&LT;&Func键LT; T,BOOL&GT;&GT;被作为参数传入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆