Как проверить код, связанный с базой данных, с помощью NUnit?


Я хочу написать модульные тесты с NUnit, которые попали в базу данных. Я хотел бы иметь базу данных в согласованном состоянии для каждого теста. Я думал, что транзакции позволят мне "отменить" каждый тест, поэтому я искал и нашел несколько статей из 2004-05 на тема:

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

Это здорово, но...

  1. это функциональность существует где-то в Нанит изначально?
  2. была ли эта техника улучшена за последние 4 года?
  3. Это все еще лучший способ проверить код, связанный с базой данных?

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

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

5 58

5 ответов:

NUnit теперь имеет атрибут [Rollback], но я предпочитаю делать это по-другому. Я использую TransactionScope класса. Есть несколько способов его использования.

[Test]
public void YourTest() 
{
    using (TransactionScope scope = new TransactionScope())
    {
        // your test code here
    }
}

Так как вы не сказали TransactionScope зафиксировать это будет откат автоматически. Он работает даже в случае сбоя утверждения или какого-либо другого исключения.

другой способ-использовать [SetUp] для создания TransactionScope и [TearDown] для вызова Dispose на нем. Он вырезает некоторые дублирование кода, но выполняет то же самое.

[TestFixture]
public class YourFixture
{
    private TransactionScope scope;

    [SetUp]
    public void SetUp()
    {
        scope = new TransactionScope();
    }

    [TearDown]
    public void TearDown()
    {
        scope.Dispose();
    }


    [Test]
    public void YourTest() 
    {
        // your test code here
    }
}

это так же безопасно, как оператор using в отдельном тесте, потому что NUnit гарантирует, что вызывается TearDown.

сказав Все, что я думаю, что тесты, которые попали в базу данных, на самом деле не являются модульными тестами. Я все еще пишу их, но я думаю о них как об интеграционных тестах. Я все еще вижу в них ценность. Одно место, где я часто использую их, - это тестирование кода LINQ to SQL. Я не использую дизайнера. Я рукой пишу и атрибуты ДТО по. Я, как известно, ошибаюсь. Интеграционные тесты помогают поймать мою ошибку.

Я просто пошел в группу пользователей .NET, и ведущий сказал, что он использовал SQLlite в тестовой установке и демонтаже и использовал опцию in memory. Он должен был немного подделать соединение и явно уничтожить соединение, но это дало бы чистый DB каждый раз.

http://houseofbilz.com/archive/2008/11/14/update-for-the-activerecord-quotmockquot-framework.aspx

для такого рода тестирования я экспериментировал с NDbUnit (работая совместно с NUnit). Если память не изменяет, это был порт DbUnit с платформы Java. У него было много гладких команд для того, что вы пытаетесь сделать. Проект, кажется, переехал сюда:

http://code.google.com/p/ndbunit/

(раньше это было в http://ndbunit.org).

источник, кажется, доступен через это ссылка на сайт: http://ndbunit.googlecode.com/svn/trunk/

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

Как правило, я полагаюсь на ORM для моего datalayer, и поэтому я не пишу модульные тесты для многого там. Я не чувствую необходимости в модульном тестовом коде, который я не пишу. Для кода, который я добавляю в слой, я обычно используйте инъекцию зависимостей, чтобы абстрагировать фактическое соединение с базой данных, чтобы при тестировании моего кода он не касался фактической базы данных. Сделайте это в сочетании с издевательской структурой для достижения наилучших результатов.

рассмотрите возможность создания сценария базы данных, чтобы вы могли запускать его автоматически из NUnit, а также вручную для других типов тестирования. Например, если вы используете Oracle, то запустите SqlPlus из NUnit и запустите сценарии. Эти сценарии, как правило, быстрее писать и легче читать. Кроме того, очень важно, что запуск SQL из жабы или эквивалента более освещен, чем запуск SQL из кода или прохождение ORM из кода. Как правило, я создам как сценарий установки, так и сценарий демонтажа и поместите их в методы настройки и демонтажа.

следует ли вам вообще проходить через БД из модульных тестов-это еще одно обсуждение. Я считаю, что это часто имеет смысл сделать. Для многих приложений база данных является абсолютным центром действия, логика сильно настроена, и все другие технологии, языки и методы передают призраки. И с ростом функциональных языков мы начинаем понимать, что SQL, как и JavaScript, на самом деле является отличным языком что было под носом все эти годы.

Так же, как в стороне, Linq to SQL (который мне нравится в концепции, хотя я никогда не использовал) почти кажется мне способом сделать raw SQL из кода, не признавая того, что мы делаем. Некоторые люди любят SQL и знают, что им это нравится, другие любят его и не знают, что им это нравится. :)