0

The suggested answer uses It.IsAny<> which we have a firm dictate not to use.

So I'm attempting to verify the Expression<Func<Foo, bool>> and run it over my collection:

Expression<Func<Foo, bool>> testExpression = exp =>
    exp.Bars.Any(a => a.Bar.BarString == barString);

_fooRepository.Setup(f => f.GetAllListAsync(It.Is<Expression<Func<Foo, bool>>> 
   (exp => exp == testExpression)))
.Returns(Task.FromResult(fooList.Where(testExpression.Compile()).ToList()))
.Verifiable();

I gave several attempts to the answer, but overloading the return with the predicate doesn't let me execute it over my strongly typed list.


I have a method that takes a string and executes a lambda over the Repository to get all instances that match (but only expecting one).

For instance:

    var foo = await _fooRepository.GetAllListAsync(
        f => f.Bars.Any(b => b.Bar.BarString == barString));

There is some verification that ensures only one was actually returned - then a property of foo is returned (we'll say fooId).

What I'm having issues with, is setting up a mock where I can verify - given a list of Foo's, does the lambda return the expected results?

My test at this point is pretty hacked up (I've been rewriting it and working on it for far too long):

const string fooId = "fooId";
const string barString = "barString";
var fooList = new List<FooList>()
{
    new Foo()
    {
        FooId = fooId,
        Bars = new List<FooBar>()
        {
            new FooBar()
            {
                Bar = new Bar()
                {
                    BarString = barString
                }
            }
        }
    },
    new Foo()
    {
        FooId = "other foo",
        Bars = new List<FooBar>()
        {
            new FooBar()
            {
                Bar = new Bar()
                {
                    BarString = "other bars"
                }
            }
        }
    }

};

_fooRepository.Setup(f => f.GetAllListAsync(It.IsAny<Expression<Func<Foo, bool>>>()))
    .Returns(Task.FromResult(fooList))
    .Verifiable();

I've tried building out an expectedExpression via:

Expression<Func<Foo, bool>> expectedExpression = exp => 

And that's where I hang - because, I can create the expression no sweat. I'm not sure how to get my fooList to have the expression executed over it.

I have seen some examples of a Lambda being used in the .Returns() method - but that doesn't seem to be the route I want it to take because I want it to test the method, not a lambda I provide the test.

Any direction would be greatly appreciated.

Dan Orlovsky
  • 1,045
  • 7
  • 18
  • Does this answer your question? [Moq'ing methods where Expression> are passed in as parameters](https://stackoverflow.com/questions/5196669/moqing-methods-where-expressionfunct-bool-are-passed-in-as-parameters) – devNull Mar 05 '20 at 23:54
  • 1
    ^ that example does use the `Returns()` method, but I believe that is the route you should be taking. The overload of `Returns()` in the answer there provides the value of the expression that was passed into the method. You can use that expression against your `fooList` to ensure that it filters the results correctly – devNull Mar 05 '20 at 23:56
  • While I've already seen that one - I did go back and try, maybe I missed something. – Dan Orlovsky Mar 06 '20 at 03:18

1 Answers1

0

What I was missing was I had to pass in the expected results of the entire iteration.

For example:

var fooList = new List<FooList>()
{
    new Foo()
    {
        FooId = fooId,
        Bars = new List<FooBar>()
        {
            new FooBar()
            {
                Bar = new Bar()
                {
                    BarString = barString
                }
            }
        }
    },
    new Foo()
    {
        FooId = "other foo",
        Bars = new List<FooBar>()
        {
            new FooBar()
            {
                Bar = new Bar()
                {
                    BarString = "other bars"
                }
            }
        }
    }

};

I then had to declare the iteration with the expected results:

Func<Expression<Func<Foo, bool>>, bool> exprIsGood = expr => 
{
    var func = expr.Compile();

    return func(fooList[0])
        && !func(fooList[1]);
};

And finally, I can verify the lambda and pass the expected return:

_fooRepository.Setup(
    f => f.GetAllListAsync(
        It.Is<Expression<Func<Foo, bool>>>(exp => exprIsGood(exp))))
    .Returns(Task.FromResult(new List<Foo> { fooList[0] }))
    .Verifiable();
Dan Orlovsky
  • 1,045
  • 7
  • 18