Подтвердить что ты не робот

Как я могу unit test Первичные сопоставления кода Entity Framework?

Я использую Code First для сопоставления классов существующей базе данных. Мне нужно сделать unit test эти сопоставления, которые представляют собой сочетание основанных на соглашениях, основанных на атрибутах и ​​fluent-api.

Чтобы unit test, мне нужно подтвердить, что свойства классов сопоставляются с правильными именами таблиц и столбцов в базе данных. Этот тест необходимо выполнить против контекста и сначала должен охватывать все параметры конфигурации для кода.

На очень высоком уровне я бы хотел утверждать что-то вроде (псевдокода):

Assert.IsTrue(context.TableFor<Widget>().IsNamed("tbl_Widget"));
Assert.IsTrue(context.ColumnFor<Widget>(w => w.Property).IsNamed("WidgetProperty"));
4b9b3361

Ответ 1

Еще одна идея - использовать Linq и ToString().

Для примера:

context.Widget.Select(c => c.Property).ToString()

Это приведет к этому для поставщика SQL Server:

"SELECT [Var_3].[WidgetProperty] AS [WidgetProperty] FROM [dbo].[Widget]..."

Теперь мы могли бы скрыть все это в некотором методе Extension, который и анализирует полученный SQL, он будет выглядеть почти как ваш псевдокод:

Assert.IsTrue(context.Widgets.GetSqlColumnNameFor(w => w.Property).IsNamed("WidgetProperty"));

Черновик для расширения:

public string GetSqlColumnNameFor<TSource>(this DbSet<T> source, Expression<Func<TSource, TResult>> selector)
{
    var sql = source.Select(selector).ToString();

    var columnName = sql... // TODO : Some regex parsing

    return 
       columnName;
}

Аналогичным образом мы могли бы создать GetSqlTableNameFor().

UPDATE: я решил найти некоторые посвященные SQL Parsers, поэтому это решение более общее, очевидно, что для .NET существует такая вещь:

http://www.dpriver.com/blog/list-of-demos-illustrate-how-to-use-general-sql-parser/generate-internal-query-parse-tree-in-xml-for-further-processing/

Ответ 2

Единственный способ, которым я могу придумать, чтобы охватить все возможные варианты, - использовать инструменты Entity Framework Power Tools для предварительной компиляции представлений вашего DbContext и, возможно, использовать комбинацию отражения этого сгенерированного типа и RegEx в сгенерированном сам код, чтобы проверить, все ли карты, как вы хотите. Мне очень больно.

Еще одна вещь, которая приходит на ум - это создать фасад вокруг DbModelBuilder, чтобы перехватить и проверить все, что проходит через него, но я не знаю, справится ли это с материалами, основанными на конвенциях. Также звучит болезненно.

Как менее полная, но гораздо более простая альтернатива, вы можете, вероятно, выбить большую часть этого, переключаясь на атрибутное отображение, где это возможно. Это позволит вам создать базовый тестовый класс, например ModelTesting <TEntity> , который включает в себя несколько методов тестирования, которые используют отражение для проверки того, что TEntity имеет:

  • Один атрибут TableAttribute.
  • Каждое свойство имеет один атрибут ColumnAttribute или NotMappedAttribute.
  • По крайней мере одно свойство с ключом.
  • Каждый тип свойства сопоставляется с совместимым типом базы данных.

Вы даже можете зайти так, чтобы обеспечить соблюдение соглашения об именах, основанное на именах свойств и класса (с предостережением для типов таблиц на иерархию). Также можно было бы проверить сопоставления внешних ключей. Это базовый класс с однократной записью, который вы можете получить один раз для каждого из ваших типов моделей и поймать большинство своих ошибок (ну, в любом случае, он улавливает мою часть).

Все, что не может быть представлено атрибутами, такими как наследование TPH и т.д., становится немного сложнее. Тест интеграции, который запускает DbContext и делает FirstOrDefault для Set <TEntity> (), вероятно, будет охватывать большинство этих баз, если ваш DbContext не создает вашу базу данных для вас.

Ответ 3

Если вы написали метод

public static string ToMappingString(this Widget obj)

Затем вы можете легко проверить это с помощью тестов на утверждение (www.approvaltests.com или nuget)

Здесь есть видео: http://www.youtube.com/watch?v=vKLUycNLhgc

Однако, если вы хотите проверить "Мои объекты сохраняют и извлекают себя", Тогда это идеальное место для "Тестирования на основе теории"

Тестирование на основе теории Большинство unit test принимают форму

Given A,B expect C

Тестирование на основе теории

Given A,B expect Theory

Красота этого заключается в том, что нет необходимости беспокоиться о том, какая конкретная форма A и B взята, поскольку вам не нужно знать C, поэтому любой случайный генератор будет работать.

Пример 1: Тестирование методов добавления и вычитания

Обычно у вас будет материал вроде

Assert.AreEqual(5, Add(2,3));
Assert.AreEqual(9, Add(10,-1));
Assert.AreEqual(10, Add(5,5));
Assert.AreEqual(7, Subtract(10,3));

Однако, если вы написали теоретический тест, это будет выглядеть как

for(int i = 1; i < 100; i++)
{ 
    int a = random.Next();
    int b = random.Next();
    Assert.AreEqual(a, Subtract(Add(a,b),b, string.Format("Failed for [a,b] = [{0},{1}], a,b));        
}

Теперь, когда вы понимаете теоретическое тестирование на основе теории, теория, которую вы пытаетесь протестировать,

Given Model A
When A is stored to the database, and retrieved the resulting object is equal to A