2013-12-21 4 views
5

Я пытаюсь узнать, как издеваться над моим общим хранилищем, чтобы я мог тестировать все свои службы.NHibernate Unit Testing Mocking/In Memory Database

Im используя NHibernate Свободный доступ для обработки данных и Ninject для зависимости (я не заинтересован в тестировании этого)

Мой репозиторий интерфейс выглядит как:

public interface IRepository<TEntity> where TEntity : class 
{ 
    IQueryable<TEntity> GetAll(); 
    TEntity Get(int key); 
    void Insert(TEntity entity); 
    void Update(TEntity entity); 
    void Delete(int id); 
} 

И фактическое хранилище выглядит как :

public class GenerRepository<TEntity> : IRepository<TEntity>where TEntity : Entity 
{ 
    protected ISession Session{get { return NHibernateHelper.OpenSession(); }} 
    public IQueryable<TEntity> GetAll(){return Session.Query<TEntity>();} 
    public TEntity Get(int key){return Session.Get<TEntity>(key);} 
    public void Insert(TEntity entity){Session.Save(entity);} 
    public void Update(TEntity entity){Session.Update(entity);} 
    public void Delete(int id){Session.Delete(Session.Load<TEntity>(id));} 
} 

Все мои услуги выполняют следующие действия: создайте репозиторий и используйте его.

Я читал так много статей о том, как это сделать, но ни один из них не прост или не объяснен. Поэтому любые советы между созданием тестового универсального репозитория или даже издевательством над ним. Мне также было бы интересно создать базу данных в памяти, но как мне настроить конфигурацию для свободного nhibernate в моем тестовом проекте без редактирования кода в моем реальном проекте?

Возможно ли, чтобы общий репозиторий попал в список Tentity, а не в базу данных или в базу данных памяти.

Спасибо за чтение и с нетерпением ждем совета.

+0

Это возможно. Если вы пойдете этим путем, имейте в виду, что поставщик LINQ более ограничен, чем объекты LINQ 2, что означает, что вы можете завершить тестирование вашего модуля с «List », а приложение сбой при запросе на базу данных. –

+0

Ahh спасибо за это, Так как бы вы посоветовали мне проверить это? Можете ли вы привести мне пример? – LmC

+0

Может быть, это против «чистоты» модульного тестирования (поскольку он переходит на территорию простых тестов интеграции), но я обычно использую [базу данных SQLite в памяти] (http: // ayende.ком/блог/3983/NHibernate-модульное тестирование). С последними версиями NHibernate и драйверами у меня не было ни одного запроса NHibernate LINQ, который завершился бы неудачей на SQLite (при работе на SQL Server). –

ответ

4

Есть несколько способов для достижения этой цели,

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

  2. Используйте реальную базу данных и используйте область транзакций для тестирования (начиная транзакцию и сделайте тест, и как только все будет сделано, только откат транзакции), это действительно хороший подход, и я использую его для крупномасштабного проекта. Однако одна из проблем заключается в том, что для запуска тестов требуется много времени (у меня около 3500 тестов, и для их запуска требуется всего 40 минут)

  3. Используйте поддельные репозитории (имеющие внутренний список сущностей) для проверки бизнес-логики и использования фактических репозиториев для проверки сопоставлений. Такой подход потребует дополнительных усилий для создания и поддержки поддельных репозиториев. Те же тесты, выполненные в реальных хранилищах, могут выполняться на поддельных хранилищах для проверки подделок. При таком подходе выполнение теста будет быстрее.

4

Могу ответить, может быть, комментарий. Потому что я хотел бы вам сказать: не делайте этого. Не тратьте время на то, чтобы создать подделку данных, которые нужно вернуть с сохранением. И не вкладывайте свое время, чтобы: взять данные от клиента и поместить их в какую-то виртуальную БД в памяти.

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

Скорее потратите некоторое время на создание сценариев, в которых будут заполняться тестовые данные. Данные, которые вы можете ожидать в тестах: при выполнении бизнес проверки, Service сериализации данных ...

Также смотрите здесь: Ayende: NHibernate Unit Testing. Экстракт:

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

Примечание: некоторое время назад мы использовали все испытания в транзакции Begin() и Rollback(). Это выглядело хорошо. Но мы поняли, что много вещей - из-за отсутствия Flush() звонок - не был протестирован полностью вниз (например, установка не-null).

+0

Как звук, я использую Ninject для привязки объекта ISessioNFactory в своем классе к методу NHibernateHelper, который либо создает один, либо использует уже сделанный (этот объект статичен), то в моем тесте я отправляю свой поддельный ISessionFactory, который упоминается в вашей ссылке, как создать? – LmC

+0

Дело в том, что мы должны заботиться о репозитории (а не статической фабрике сеансов). Скажем, нам нужно получить некоторые данные с помощью «GetAll()» - данных, которые невозможно поместить в БД с помощью тестовых скриптов. Тогда мы должны получить прибыль от ** IoC **. Мы наследуем новый класс 'TestRepository', и там мы изменим реализацию' GetAll() '. Мы научим * Ninject * использовать эту реализацию (или передать ее через публичный сеттер) для этого конкретного теста. Но для обычных тестов мы ** будем использовать «реальную» ** реализацию. –

6

Я должен согласиться с Radim, что модуль тестирования nhibernate, издевав функциональность nhibernate в большинстве случаев не так, как вы хотите.

Если вы не хотите тестировать сложную бизнес-логику, основанную на данных, которые вы получаете через nhibernate, то это совершенно нормально.

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

Если вы нацеливаете сервер MSSQL, я бы не использовал другой тип базы данных. Вместо этого есть SQL Express, который имеет все функции реального сервера. MSSQL Express может быть установлен с локальной БД. Это позволит вам загружать файлы mdf через строку подключения, которая будет более или менее создавать экземпляр экземпляра сервера MSSQL ...

Я использовал это для тестирования интеграции, и он работает очень хорошо.

  1. Создать файл базы данных в тестовом модуле проекта
  2. В зависимости от модели (код первого/дб первый) пусть NHibernate создать схему, иначе простую заселить схему в этот файл базы данных
  3. Добавьте файл для элементов развертывания ваших тестовых настроек, чтобы файл был скопирован в целевой целевой каталог
  4. Создать строку соединения, в которой используется скопированный файл базы данных. Пример Строка соединения: Data Source=(LocalDB)\v11.0;AttachDbFileName=[whateverthepathis]\DatabaseFileName.mdf;InitialCatalog=DatabaseName;Integrated Security=True;MultipleActiveResultSets=True
  5. Выполнить тесты

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