Автоматизированные тесты для перевода Expression

1

Я использую PredicateBuilder для создания многоразовых выражений в качестве возвращаемых значений объектов. Например:

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

Я хочу иметь автоматические тесты, которые определяют, может ли конкретное выражение трансформироваться в T-SQL с помощью Entity Framework (т. NotSupportedException Что он не NotSupportedException при выполнении). Я не могу найти что-либо в Интернете - возможно ли это (кажется, должно быть)?

  • 0
    Разве вы не можете протестировать реализацию интерфейса?
Теги:
unit-testing
entity-framework

2 ответа

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();
  • 0
    Браво :) никогда не думал об использовании ToString() . Тем не менее, это позор, что EF требует экземпляр DbContext (возможно, это изменится в EF7)
  • 0
    @AlexG Без DbContext он не мог знать, какой сервер вы используете ... Oracle и MSSQL могут иметь различную поддержку для различных методов.
Показать ещё 2 комментария
1

Выполняет это очень простое решение:

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

В более старых версиях EF (или с использованием ObjectContext) вы могли бы попробовать "вручную" скомпилировать запрос с помощью CompiledQuery.Compile, но это не поддерживается DbContext.

  • 1
    Это хорошая идея, но преобразование запроса в строку без ее выполнения является предпочтительным для производительности.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню