Moq Expression with Constraint ... It.Is<Expression<Func<T, bool>>>
It seems that the real problem here is how to compare two lambda expressions, as you try to do in the It.Is<Expression<Func<UserBinding, bool>>>
(criteria => criteria == testExpression)
clause. Using @neleus's answer to this question, I could came up with this test that actually passes:
readonly Mock<IBindingManager> bindingManager = new Mock<IBindingManager>();
[Test]
public void TestMethod()
{
Expression<Func<string, bool>> testExpression = binding => (binding == "Testing Framework");
bindingManager.Setup(c => c.GetUserBinding(It.Is<Expression<Func<string, bool>>>(
criteria => LambdaCompare.Eq(criteria, testExpression)))).Returns(new List<string>());
var oc = new OtherClass(bindingManager.Object);
var actual = oc.Test(b => b == "Testing Framework");
Assert.That(actual, Is.Not.Null);
bindingManager.Verify(c => c.GetUserBinding(It.Is<Expression<Func<string, bool>>>(
criteria => LambdaCompare.Eq(criteria, testExpression))), Times.Once());
}
Please note the use of the LambdaCompare.Eq
static method to compare that the expressions are the same. If I compare the expressions just with ==
or even Equals
, the test fails.
When I was looking for the way to to mock Where() and filter some data, in code under tests looks like:
Repository<Customer>().Where(x=>x.IsActive).ToList()
I could design such example based on answers form others:
var inputTestDataAsNonFilteredCustomers = new List<Customer> {cust1, cust2};
var customersRepoMock = new Mock<IBaseRepository<Customer>>();
IQueryable<Customer> filteredResult = null;
customersRepoMock.Setup(x => x.Where(It.IsAny<Expression<Func<Customer, bool>>>()))
.Callback((Expression<Func<Customer, bool>>[] expressions) =>
{
if (expressions == null || expressions.Any() == false)
{
return;
}
Func<Customer, bool> wereLambdaExpression = expressions.First().Compile(); // x=>x.isActive is here
filteredResult = inputTestDataAsNonFilteredCustomers.Where(wereLambdaExpression).ToList().AsQueryable();// x=>x.isActive was applied
})
.Returns(() => filteredResult.AsQueryable());
Maybe it will be helpful for feather developers.