表达式翻译的自动化测试

时间:2015-03-25 09:42:29

标签: c# entity-framework unit-testing

我正在使用PredicateBuilder来构建可重用表达式作为对象的返回值。例如:

public interface ISurveyEligibilityCriteria
{
    Expression<Func<Client, bool>> GetEligibilityExpression();
}

我想要进行自动化测试,以确定某个特定表达式是否可以通过实体框架转换为T-SQL(即它在执行&#34;时不会抛出NotSupportedException。 。我无法在互联网上找到任何东西 - 这是否可能(似乎应该如此)?

2 个答案:

答案 0 :(得分:2)

您可以创建一个包含表达式的LINQ语句,然后检查它是否可以在不实际执行的情况下进行翻译:

var connString = @"server=x;database=x";
using(var db = new MyContext(connString))
{
    // ToString() shows the generated SQL string.
    var sql = db.Entities.Where(generatedExpression).ToString();
    Assert.IsTrue(sql.StartsWith("SELECT");
}

Assert中,您可以测试您希望成为生成的SQL字符串一部分的任何内容,但当然如果表达式无法翻译,则测试将失败,因为例如抛出NotSupportedException


您可以将其包装成一个方便的扩展方法:

public static class EntityFrameworkExtensions
{
    public static void CompilePredicate<T>(this DbContext context, Expression<Func<T, bool>> predicate)
        where T : class
    {
        context.Set<T>().Where(predicate).ToString();
    }
}

然后在你的测试中:

// act
Action act = () => context.CompilePredicate(predicate);

// assert
act.ShouldNotThrow();

答案 1 :(得分:1)

一个非常简单的解决方案是执行它:

using (var context = ...)
{
    // The query will return null, but will be executed.
    context.Clients.Where(GetEligibilityExpression())
                   .Where(() => false)
                   .SingleOrDefault(); 
}

在旧版本的EF(或使用ObjectContext)中,您可以尝试&#34;手动&#34;使用CompiledQuery.Compile编译查询,但DbContext不支持。