Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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()));
like image 772
Channafow Avatar asked Dec 03 '13 23:12

Channafow


People also ask

Can a lambda statement return a value?

A lambda expression is a short block of code which takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.

Can we write a Parameterless lambda expression?

No, there isn't. Lambda expressions are optimised (in terms of syntax) for the single parameter case. I know that the C# team feels your pain, and have tried to find an alternative. Whether there ever will be one or not is a different matter.

Can you use ref and out parameters in lambda expression if declared outside?

In lambda expressions, you can't use the ref or out parameters.

What is lambda expression in .NET framework?

You use a lambda expression to create an anonymous function. Use the lambda declaration operator => to separate the lambda's parameter list from its body. A lambda expression can be of any of the following two forms: Expression lambda that has an expression as its body: C# Copy.


1 Answers

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()));
like image 197
Chris Mantle Avatar answered Sep 18 '22 10:09

Chris Mantle