How to test for a Match with FakeItEasy on a predicate call?

c#, fakeiteasy, lambda, predicate

Solution

Sorry I should have answered this earlier. It is true that Blair Conrad and I had a chat and he helped me understand how to test the predicates better. Based on his recommendation I came up with the following solution.

In my tests I created a helper Expression extractor show below:

private static string ExpressionExtractor(Expression<Func<CrossReferenceRelationshipEF, bool>> predicate)
{
    var expression = ((BinaryExpression) ((LambdaExpression) ((MethodCallExpression) predicate.Body).Arguments[1]).Body);
    var value = Expression.Lambda<Func<object>>(Expression.Convert(expression.Right, typeof (object))).Compile().Invoke();

    return value.ToString();
}

And then in my tests I could do my assert like this:

//Assert        
A.CallTo(() => crossReferenceRelationshipRepositoryMock.SearchFor(A<Expression<Func<CrossReferenceRelationshipEF, bool>>>.That
    .Matches(exp => ExpressionExtractor(exp) == "20/01/2014 14:06:55")))
    .MustHaveHappened(Repeated.Exactly.Twice);

Problem

I have the following call in my code: ``` var dbResults = new List<CrossReferenceRelationshipEF>(); dbResults = dateTimeFilter == null ? new List<CrossReferenceRelationshipEF>( CrossReferenceRelationshipRepository.GetAll() .ToList().OrderBy(crr => crr.ToPartner)) : new List<CrossReferenceRelationshipEF>( CrossReferenceRelationshipRepository.SearchFor( crr => crr.HistoricEntries .Any(he => he.ModifiedDatetime > dateTimeFilter)) .ToList().OrderBy(crr => crr.ToPartner)); ``` and I am trying to use FakeItEasy to verify that when the `dateTimeFilter` has a value, the `SearchFor(…)` is being called within my repository with the correct Function. So my test looks something like this: ``` A.CallTo(() => crossReferenceRelationshipRepositoryMock.SearchFor(A<Expression<Func<CrossReferenceRelationshipEF,bool>>>.That .Matches(exp => Expression.Lambda<Func<DateTime>>(((BinaryExpression)exp.Body).Right).Compile().Invoke() == filterByDate))) .MustHaveHappened(Repeated.Exactly.Once); ``` Which is not correct. What would be a way to test the whether or not I am calling `SearchFor(…)` with the correct expression? ``` crr => crr.HistoricEntries.Any(he => he.ModifiedDatetime > dateTimeFilter) ``` The actual value being passed into `SearchFor(…)` is `DateTime.MinValue` so I changed my assertion to: ``` A.CallTo(() => crossReferenceRelationshipRepositoryMock.SearchFor(A<Expression<Func<CrossReferenceRelationshipEF, bool>>>.That .Matches(exp => Expression.Lambda<Func<DateTime>>(((BinaryExpression)exp.Body).Right).Compile().Invoke() == DateTime.MinValue))) .MustHaveHappened(Repeated.Exactly.Once); ``` which is failing and the exception I am getting is ``` System.InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.MethodCallExpressionN' to type 'System.Linq.Expressions.BinaryExpression'. ``` and I am not sure what I am doing wrong...

Original source