繁体   English   中英

模拟Linq“任何”与Moq的谓词

[英]Mock Linq `Any` predicate with Moq

我正在尝试使用以下代码在我的存储库中模拟AnyAsync方法,但存储库始终返回false

AnyAsync的签名是:

Task<bool> AnyAsync<TEntity>(Expression<Func<TEntiry, bool>> predicate)

我尝试了以下设置:

1:

mockCustomerRepository.Setup(r => r.AnyAsync(c => c.Email == "some@one.com"))
   .ReturnsAsync(true);

2:

Expression<Func<CustomerEntity, bool>> predicate = expr => 
    expr.CustomerPerson.Email == "some@one.com";

mockCustomerRepository.Setup(r => r.AnyAsync(It.Is<Expression<Func<CustomerEntity, bool>>>
   (criteria => criteria == predicate))).ReturnsAsync(true);

3:

mockCustomerRepository.Setup(r => r.AnyAsync(It.IsAny<Expression<Func<CustomerEntity, bool>>>()))
    .ReturnsAsync(true);

我的测试:

public class Test 
{
    Mock<ICustomerRepository> mockCustomerRepository;

    public Test()
    {
        mockCustomerRepository = new Mock<ICustomerRepository>();
    }

    [Fact]
    public async Task CustomerTest()
    {   
        var customer = ObjectFactory.CreateCustomer(email: "some@one.com");
        var sut = new CustomerService(mockCustomerRepository.Object);

        var result = await sut.ValidateCustomerAsync(customer);
        .
        .
        .
    }
}

我的CustomerService.ValidateCustomerAsync方法:

public async Task<OperationResult> ValidateCustomerAsync(CustomerEntity customer)
{
    var errors = new List<ValidationResult>();

    if (await _repository.AnyAsync(c => c.Email == customer.Email))
        errors.Add(new ValidationResult("blah blah")));

我也读过这个,但它也不行。

以下代码段显示了模拟AnyAsync方法的正确方法:

[TestMethod]
public async Task TestMethod1()
{
    var fakeCustomerRepo = new Mock<ICustomerRepository>();
    var foo = false;
    fakeCustomerRepo.Setup(repository => repository.AnyAsync(It.IsAny<Expression<Func<CustomerEntity, bool>>>()))
        .Callback<Expression<Func<CustomerEntity, bool>>>(
            expression =>
            {
                var func = expression.Compile();
                foo = func(new CustomerEntity() {Email = "foo@gmail.com"});
            })
        .Returns(() => Task.FromResult(foo));

    var customer = new CustomerEntity() {Email = "foo@gmail.com"};
    var result = await fakeCustomerRepo.Object.AnyAsync<CustomerEntity>(c => c.Email == customer.Email);
    Assert.IsTrue(result);

    customer = new CustomerEntity() { Email = "boo@gmail.com" };
    result = await fakeCustomerRepo.Object.AnyAsync<CustomerEntity>(c => c.Email == customer.Email);
    Assert.IsFalse(result);
}

使用上面的设置,您可以验证作为单位行为一部分的谓词。

我认为你遇到了匹配谓词的困难。 Func的Func或表达式使用引用相等,因此只使用==来比较这两个实例是行不通的。 (作为一般规则,如果你不能让predicate1.Equals(predicate2)返回true,那么Moq的参数匹配器将不会匹配。)

这有点不正统,但我引用了你对FakeItEasy匹配器的类似问题的回答 ,这反过来又指出了许多用于验证谓词的技巧。

我只能看到应该导致这个问题的两个选择:

1.存储库方法不是来自您应该模拟返回所需值的接口,因为它没有标记为virtual

2.使用moq时,方法中使用的类型( TEntity )不匹配。

AnyAsync<TEntity>(Expression<Func<TEntity, bool>> 

你可以设置为让我们说MemberEntity并使用CustomerEntity调用ValidateCustomerAsync

也许我错了,但是,据我所知,对于只返回任务的方法,可以并且应该使用.Returns(Task.FromResult(default(object)))

所以在你的情况下,它将是mocksCustomerRepository.Setup(r => r.AnyAsync(c => c.Email == "some@one.com")).Returns(Task.FromResult(true));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM