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. Я не пользуюсь дизайнером. Я вручную пишу DTO и атрибуты. Я был известен, чтобы понять это неправильно. Интеграционные тесты помогают поймать мою ошибку.