Как лучше всего создать тестовую БД при выполнении TDD? - PullRequest
17 голосов
/ 13 ноября 2008

Какова лучшая практика для создания уровней персистентности теста при создании сайта ASP.NET (например, сайта ASP.NET MVC)?

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

Какие практики делают люди, когда хотят (заглушки?) Выдумать слой постоянства для быстрой и быстрой разработки? Я использую Dependency Injection, чтобы справиться с этим и получить некоторые жестко запрограммированные результаты для моего слоя персистентности (который действительно ручной и скучный).

Что делают другие люди? Примеры и ссылки были бы потрясающими:)

UPDATE

Просто небольшое обновление: до сих пор я получаю немало преимуществ от наличия поддельного репозитория и репозитория SQL - где каждый класс реализует интерфейс. Затем, используя DI (я использую StructureMap), я могу переключаться между своим поддельным репозиторием или репозиторием SQL. Пока что работает хорошо :)

(также страшно подумать, что я задал этот вопрос почти 11 месяцев назад, с того момента, когда я редактировал это, прямо сейчас!)

Ответы [ 6 ]

3 голосов
/ 13 ноября 2008

Предполагается, что вы используете шаблон репозитория из магазина витрины MVC Роба Конери:

http://blog.wekeroad.com/mvc-storefront/mvc-storefront-part-1/

Я следовал учебнику Роба Конери, но столкнулся с тем же желанием, что и вы. Лучше всего переместить созданные вами репозитории Mock в отдельный проект под названием Mocks, после чего вы можете легко заменить их реальными при создании экземпляра вашего сервиса. Если вы чувствуете себя авантюрным, вы можете создать фабрику, которая берет значение из конфигурационного файла для создания экземпляра макета или реального хранилища,

, например

public static ICatalogRepository GetCatalogRepository(bool useMock)
{
     if(useMock)
          return new FakeCatalogRepository();
     else
          return new SqlCatalogRepository();
}

или используйте инфраструктуру внедрения зависимостей:)

container.Resolve<ICatalogRepository>();

Удачи!

РЕДАКТИРОВАТЬ: В ответ на ваши комментарии звучит так, как будто вы хотите использовать список и LINQ для эмуляции операций БД, например, GetProducts, Магазин товаров. Я делал это раньше. Вот пример:

public class Product
{
     public int Identity { get; set; }
     public string Name { get; set; }
     public string Description { get; set; }
     //etc
}

public class FakeCatalogRepository()
{
     private List<Product> _fakes;

     public FakeCatalogCatalogRepository()
     {
          _fakes = new List<Product>();

          //Set up some initial fake data
          for(int i=0; i < 5; i++)
          {
              Product p = new Product
              {
                 Identity = i,
                 Name = "product"+i,
                 Description = "description of product"+i
              };

              _fakes.Add(p);
          }
     }

     public void StoreProduct(Product p)
     {
         //Emulate insert/update functionality

         _fakes.Add(p);
     }

     public Product GetProductByIdentity(int id)
     {
          //emulate "SELECT * FROM products WHERE id = 1234
          var aProduct = (from p in _fakes.AsQueryable()
                         where p.Identity = id
                         select p).SingleOrDefault();

          return aProduct;
     }
}

Это имеет больше смысла?

0 голосов
/ 18 января 2012

Я знаю, что этот вопрос немного стар, но я наконец-то нашел ответ:)

Во-первых, используйте RavenDb (Embedded) . Он является частью RavenDb Document Database . Это полностью в памяти базы данных и прекрасно работает с модульными тестами :) Я сделал это с MSTest, NUnit и xUnit.

Во-вторых, вы можете использовать NHibernate с SqlLite, если вы не хотите использовать RavenDb. У Ayende есть сообщение об использовании этого .

0 голосов
/ 23 ноября 2008

Я использую полную базу данных в памяти с SQLite и ActiveRecord. Обычно мы удаляем и воссоздаем базу данных перед каждым интеграционным тестом, чтобы данные всегда были в известном состоянии. Содержимое базы данных вставляется через код. Итак, пример будет выглядеть так:

ActiveRecord.Initalize(lots of parameters)
ActiveRecord.DropSchema();
ActiveRecord.CreateSchema();

и затем мы просто добавляем множество клиентов или что-то еще, стиль DDD:

customerRepository.Save(customer);

Другим способом решения этой проблемы может быть использование NDbUnit для поддержания состояния базы данных.

0 голосов
/ 14 ноября 2008

Хотя я не использую Asp.Net или инфраструктуру MVC, у меня есть необходимость тестировать сервисы, не обращаясь к базе данных. Ваш вопрос вызвал написание краткого (хорошо, может быть, не так коротко) резюме, как я это делаю. Не утверждая, что это лучшее или что-то, но это работает для нас. Мы обращаемся к данным через репозиторий и при необходимости подключаем репозиторий в памяти, как описано в посте.

http://blogs.microsoft.co.il/blogs/kim/archive/2008/11/14/testable-data-access-with-the-repository-pattern.aspx

0 голосов
/ 13 ноября 2008

Я прошел путь создания таблиц и данных во время метода установки в классе модульных тестов, запуска тестов, а затем очистки во время демонтажа. Да, этот метод работает, но если вы действительно используете модульные тесты для отладки, вы всегда будете запускать установку, что-то отлаживать, а затем останавливаться в середине, не разбирая код. Это очень хрупко, и вы, вероятно, в конечном итоге (в конечном итоге) получите неверные данные в своей тестовой базе данных и / или непригодные модульные тесты. Лично я считаю, что лучше всего смоделировать слой базы данных, используя фальшивый фреймворк. Я понимаю, что иногда лучше делать логику в базе данных. В этих случаях вы можете использовать инструмент типа DBFit для написания тестов для вашего уровня базы данных.

0 голосов
/ 13 ноября 2008

Скучно или нет, я думаю, что вы на правильном пути. Я предполагаю, что вы создаете fakeRepository, который является конкретной реализацией вашего IRepository, который, в свою очередь, внедряется в ваш сервисный уровень. Это хорошо, потому что в какой-то момент в будущем, когда вы будете довольны формой ваших сущностей и поведением ваших сервисов, контроллеров и представлений, вы сможете протестировать свои настоящие репозитории, которые будут использовать базу данных для сохранения этих сущностей. , Конечно, природа этих тестов будет интеграционными, но не менее важными, если не более.

Одна вещь, которая может быть менее скучной для вас, когда придет время для создания ваших реальных репозиториев, - если вы используете nHibernate для своей настойчивости, вы сможете позволить nhibernate генерировать вашу базу данных после того, как вы создадите карты nhibernate для ваших объектов, предполагая, что не нужно использовать устаревшую схему.

Например, у меня есть следующий метод, который вызывается моей SetUpFixture для генерации моей схемы БД:

public class SchemaBuilder
{
   public static void ExportSchema()
    {
        Configuration configuration = new Configuration();
        configuration.Configure();
        new SchemaExport(configuration).Create(true, true);
    }
}

и мой SetUpFixture выглядит следующим образом:

[SetUpFixture]
public class SetUpFixture
{
    [SetUp]
    public void SetUp()
    {
        SchemaBuilder.ExportSchema();
        DataLoader.LoadData();
    }
}

, где DataLoader отвечает за создание всех моих начальных данных и тестовых данных с использованием реального хранилища.

Возможно, это не отвечает на ваши вопросы, но я надеюсь, что это поможет вам убедить вас в подходе.

Грег

...