Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock Linq `Any` predicate with Moq

I'm trying to mock AnyAsync method in my repository with below codes but repository always returns false.

The signature of AnyAsync is:

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

I tried the following setups:

1:

mockCustomerRepository.Setup(r => r.AnyAsync(c => c.Email == "[email protected]"))
   .ReturnsAsync(true);

2:

Expression<Func<CustomerEntity, bool>> predicate = expr => 
    expr.CustomerPerson.Email == "[email protected]";

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

My test:

public class Test 
{
    Mock<ICustomerRepository> mockCustomerRepository;

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

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

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

My CustomerService.ValidateCustomerAsync method:

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

I've also read this but it doesn't work too.

like image 299
Mohsen Esmailpour Avatar asked Dec 06 '25 08:12

Mohsen Esmailpour


2 Answers

The following snippet shows the correct way to mock your AnyAsync method:

[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 = "[email protected]"});
            })
        .Returns(() => Task.FromResult(foo));

    var customer = new CustomerEntity() {Email = "[email protected]"};
    var result = await fakeCustomerRepo.Object.AnyAsync<CustomerEntity>(c => c.Email == customer.Email);
    Assert.IsTrue(result);

    customer = new CustomerEntity() { Email = "[email protected]" };
    result = await fakeCustomerRepo.Object.AnyAsync<CustomerEntity>(c => c.Email == customer.Email);
    Assert.IsFalse(result);
}

using the above setup you can verify your predicate which is part of your unit behavior.

like image 164
Old Fox Avatar answered Dec 07 '25 22:12

Old Fox


I think you're running into the difficulties of matching predicates. Funcs or expressions of Funcs use reference-equality, so just using == to compare the two instances isn't going to work. (As a general rule, if you can't get predicate1.Equals(predicate2) to return true, Moq's argument matchers aren't going to match.)

This is a little unorthodox, but I refer you to my answer to a similar question for FakeItEasy matchers, which in turn points you at a number of techniques for validating predicates.

like image 23
Blair Conrad Avatar answered Dec 07 '25 21:12

Blair Conrad



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!