Заглушка / издевательство над базой данных в .Net - PullRequest
32 голосов
/ 05 апреля 2011

У меня есть веб-сервис, который в основном просто выполняет некоторые хранимые процедуры, преобразует данные и отправляет их в браузер.Никакой модный картограф ORM или что-то в этом роде.Чтобы написать тест без доступа к базе данных, я сделал следующее:

  • Я извлек все обращения к БД в один класс.Методы возвращают только объекты DataSet и DataTable.
  • Выполнил пример вызова для каждого метода и сериализовал DataSet / DataTable на диск.
  • Извлек интерфейс, предоставляющий доступ ко всем доступным методам.
  • Реализован поддельный класс базы данных, который просто загружает сериализованные данные и возвращает их.

Теперь у меня есть сериализованные примеры результатов, которые я могу проверить в своем проекте, и я могу использовать поддельную базу данных в моемтесты.

Это работает довольно хорошо для меня.Есть ли какая-то структура, которая облегчает создание и загрузку данных образца?Мой текущий проект небольшой, но я бы использовал ту же схему в более крупных проектах.

Обновление:

Очевидно, что все ответы не являются неправильными, но упускают суть.Я знаком с основами модульного тестирования.Но мой код работает с DataTables, поэтому мне придется каким-то образом подделать мои DataTables.Создание DataTable с нуля - непростая задача, и это приведет к раздуванию моих тестов и снижению читабельности.В моем случае было бы совершенно невозможно сгенерировать полезные примеры данных вручную.

Поэтому я выполнил несколько примеров вызовов для образца базы данных, чтобы получить некоторые DataTables.Я сериализовал эти таблицы на диск и использую сериализованные версии для создания моих поддельных DataTables при тестировании.Таким образом, тесты не зависят от базы данных.

Существуют различные варианты того, как структурировать код, чтобы упростить десериализацию таблиц.Но это детали реализации, которые на данный момент не нуждаются в обсуждении.Моя проблема заключается в следующем:

Управление примерами вызовов и (де) сериализация таблиц - это утомительная работа.Я искал некоторые инструменты, чтобы сделать это проще.

Ответы [ 6 ]

29 голосов
/ 13 апреля 2011

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

NBuilder - это отличная библиотека с открытым исходным кодом, которая позволяет успешно создавать большие объемы тестовых данных. Просто объедините NBuilder, несколько базовых классов объектов POCO и некоторые размышления - у вас будет множество огромных таблиц данных, которые вы можете легко объединить в наборы данных в кратчайшие сроки:

public class Person
{
    public string First { get; set; }
    public string Last { get; set; }
    public DateTime Birthday { get; set; }
}

private DataTable GenerateDataTable<T>(int rows)
{
    var datatable = new DataTable(typeof(T).Name);
    typeof(T).GetProperties().ToList().ForEach(
        x => datatable.Columns.Add(x.Name));
    Builder<T>.CreateListOfSize(rows).Build()
        .ToList().ForEach(
            x => datatable.LoadDataRow(x.GetType().GetProperties().Select(
                y => y.GetValue(x, null)).ToArray(), true));
    return datatable;
}

var dataset = new DataSet();
dataset.Tables.AddRange(new[]{
        GenerateDataTable<Person>(50),
        GenerateDataTable<Dog>(100)});
6 голосов
/ 06 апреля 2011

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

public static Transformations
{
    public static DataSet TransformationA(DataSet dataSet)
    {
        //transformation logic here
    }

    public static DataSet TransformationB(DataSet dataSet)
    {
        //transformation logic here
    }
}

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

Надеюсь, это поможет

2 голосов
/ 12 апреля 2011

Вы можете смоделировать свой класс DataAccess с помощью Rhinomocks и вернуть поддельные данные. Таким образом, вы можете протестировать код, который использует этот DataTable.

var mockedDatatable= GetMockdt();

var mocks = new MockRepository();
var dal = mocks.StrictMock<DataAccess>();

using (mocks.Record())
{
  Expect.Call(dal.GetDataTableFromDatabase("", null)).Return(mockedDatatable).IgnoreArguments();
}

using (mocks.Playback())
{
  new SomeClass(dal);
}

ОБНОВЛЕНИЕ сообщения mockdt

private static DataTable GetMockdt()
{
  var dt = new DataTable();

  dt.Columns.Add("pageHeader");
  dt.Columns.Add("templatename");
  dt.Columns.Add("pageText");
  dt.Columns.Add("pageTitleBar");
  dt.Columns.Add("metaDescription");
  dt.Columns.Add("pageStartCode");
  dt.Columns.Add("pageEndCode");
  dt.Columns.Add("templateStartCode");
  dt.Columns.Add("templateEndCode");
  dt.Columns.Add("Author");
  dt.Columns.Add("version_date");
  dt.Columns.Add("pageurl");
  dt.Columns.Add("type");
  dt.Columns.Add("isparent");
  dt.Columns.Add("pagename");
  dt.Columns.Add("parentname");
  dt.Columns.Add("url");

  var mockRow = dt.NewRow();

  mockRow["pageHeader"] = "homepage";
  mockRow["pageText"] = "<p>home</p>";
  mockRow["templatename"] = "home";
  mockRow["pageTitleBar"] = "homepages";
  mockRow["metaDescription"] = "homepages";
  mockRow["pageStartCode"] = "homepages";
  mockRow["pageEndCode"] = "homepages";
  mockRow["templateStartCode"] = "homepages";
  mockRow["templateEndCode"] = "homepages";
  mockRow["Author"] = "someone";
  mockRow["version_date"] = "";
  mockRow["pageurl"] = "home";
  mockRow["type"] = "internal";
  mockRow["isparent"] = "true";
  mockRow["pagename"] = "homepage";
  mockRow["parentname"] = "root";
  mockRow["url"] = "homepage";

  dt.Rows.Add(mockRow);

  return dt;
}
0 голосов
/ 19 апреля 2011

Извлечение http://nbuilder.org/

"Что это?

Через свободный, расширяемый интерфейс NBuilder позволяет быстро создавать тестовые данные, автоматически назначая значения свойствам иоткрытые поля, относящиеся к типу встроенных типов данных .NET (например, ints и строки). NBuilder позволяет переопределять свойства, которые вас интересуют, используя лямбда-выражения. "

0 голосов
/ 18 апреля 2011

Нет никаких инструментов для того, чтобы делать то, что вы хотите, из-за ваших требований, что ваши данные хранятся в виде DataTables, и вам нужны оригинальные данные из базы данных. Ручная часть инструментов связывает то, на что указывает (то есть ваши данные в хранилище с вашим представлением данных в коде). Вы уже сделали эту часть, и это не то, что автоматизировано.

0 голосов
/ 16 апреля 2011

По моему опыту, сквозное тестирование работало с Fluent NHibernate довольно легко. Нет оправдания не использовать такой легкий слой, когда он так много делает для тебя.

Проверка технических характеристик стойкости

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...