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

Stubbing/mocking база данных в .Net

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

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

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

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

Update:

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

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

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

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

4b9b3361

Ответ 1

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

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)});

Ответ 2

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

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

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

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

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

Ответ 3

Вы можете издеваться над своим классом DataAccess с Rhinomocks и возвращать поддельный datatable. Таким образом, вы можете протестировать код, который использует этот 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;
}

Ответ 4

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

Тестирование спецификации сохранения

Ответ 5

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

Ответ 6

Проверьте https://github.com/nbuilder/nbuilder

"Что это?

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