如何在谓词调用中测试与FakeItEasy的匹配?

Vas*_*isP 5 c# lambda predicate fakeiteasy

我的代码中有以下调用:

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));
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用FakeItEasy来验证当dateTimeFilter有一个值时,SearchFor(…)正在我的存储库中使用正确的函数调用它.

所以我的测试看起来像这样:

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);
Run Code Online (Sandbox Code Playgroud)

哪个不对.什么是测试我是否SearchFor(…)使用正确表达式调用的方法?

crr => crr.HistoricEntries.Any(he => he.ModifiedDatetime > dateTimeFilter)
Run Code Online (Sandbox Code Playgroud)

传入的实际值SearchFor(…)DateTime.MinValue因此我将断言更改为:

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);
Run Code Online (Sandbox Code Playgroud)

这是失败的,我得到的例外是

System.InvalidCastException:
  Unable to cast object of type 'System.Linq.Expressions.MethodCallExpressionN'
  to type 'System.Linq.Expressions.BinaryExpression'.
Run Code Online (Sandbox Code Playgroud)

而且我不确定我做错了什么......

Vas*_*isP 3

抱歉,我应该早点回答这个问题。确实,布莱尔·康拉德和我进行了交谈,他帮助我了解了如何更好地测试谓词。根据他的建议,我想出了以下解决方案。

在我的测试中,我创建了一个助手表达式提取器,如下所示:

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();
}
Run Code Online (Sandbox Code Playgroud)

然后在我的测试中我可以这样做我的断言:

//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);
Run Code Online (Sandbox Code Playgroud)