Channafow
Channafow

Reputation: 717

Moq: Lambda expressions as parameters and evaluate them in returns

In my unit tests I want to be able to moq the "find" function of my repository in my Unit of Work that takes in a lambda express. For example:

public virtual IQueryable<T> Find(Expression<Func<T, bool>> predicate)
{ 
    // Find OPS 
}

I created test lists to represent my dbSets in my unit tests (Also I left out a lot of abstraction to make this more simple for this question):

[TestMethod]
public void FindTest()
{
    var mockUnitOfWork = new Mock<IUnitOfWork>();
    var testList = new List<ListObject> 
    { 
        // Test values 
    }
    // Here is where I am stuck:
    mockUnitOfWork.Setup(uow => uow.Find(It.IsAny<Expression<Func<ListObject, bool>>>()))
                                   .Returns(/* ???? testList.Where(??????) ???? */);
}

I want to be able to use the lambda passed by the method calling the mock's find to search within my mocked list. Is this possible?

EDIT: Thanks to Chris for the answer. This is setup code to pass the lambda expression that is passed by the method that references the mock's function:

mockUnitOfWork
.Setup(uow => uow.Find(It.IsAny<Expression<Func<ListObject, bool>>>()))
.Returns(new Func<Expression<Func<ListObject, bool>>, IQueryable<ListObject>>(
    expr => testList.Where(expr.Compile()).AsQueryable()));

Upvotes: 15

Views: 10694

Answers (1)

Chris Mantle
Chris Mantle

Reputation: 6683

Yes, it is possible. You can pass a function to Returns that takes the expression passed to Find, compiles the expression into a Func<ListObject, bool>, and applies that to your testList:

mockUnitOfWork
    .Setup(uow => uow.Find(It.IsAny<Expression<Func<ListObject, bool>>>()))
    .Returns(new Func<Expression<Func<ListObject, bool>>, IQueryable<ListObject>>(
        expr => testList.Where(expr.Compile()).AsQueryable()));

Upvotes: 30

Related Questions