Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I test database-related code with NUnit?

I want to write unit tests with NUnit that hit the database. I'd like to have the database in a consistent state for each test. I thought transactions would allow me to "undo" each test so I searched around and found several articles from 2004-05 on the topic:

  • http://weblogs.asp.net/rosherove/archive/2004/07/12/180189.aspx
  • http://weblogs.asp.net/rosherove/archive/2004/10/05/238201.aspx
  • http://davidhayden.com/blog/dave/archive/2004/07/12/365.aspx
  • http://haacked.com/archive/2005/12/28/11377.aspx

These seem to resolve around implementing a custom attribute for NUnit which builds in the ability to rollback DB operations after each test executes.

That's great but...

  1. Does this functionality exists somewhere in NUnit natively?
  2. Has this technique been improved upon in the last 4 years?
  3. Is this still the best way to test database-related code?

Edit: it's not that I want to test my DAL specifically, it's more that I want to test pieces of my code that interact with the database. For these tests to be "no-touch" and repeatable, it'd be awesome if I could reset the database after each one.

Further, I want to ease this into an existing project that has no testing place at the moment. For that reason, I can't practically script up a database and data from scratch for each test.

like image 985
Michael Haren Avatar asked Nov 26 '08 15:11

Michael Haren


People also ask

Can NUnit be used for integration testing?

ASP.NET Core has an extremely useful integration testing framework, in the form of the NuGet package Microsoft.

What type of testing does NUnit support?

NUnit is an evolving, open source framework designed for writing and running tests in Microsoft . NET programming languages. NUnit, like JUnit, is an aspect of test-driven development (TDD), which is part of a larger software design paradigm known as Extreme Programming (XP).


1 Answers

NUnit now has a [Rollback] attribute, but I prefer to do it a different way. I use the TransactionScope class. There are a couple of ways to use it.

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

Since you didn't tell the TransactionScope to commit it will rollback automatically. It works even if an assertion fails or some other exception is thrown.

The other way is to use the [SetUp] to create the TransactionScope and [TearDown] to call Dispose on it. It cuts out some code duplication, but accomplishes the same thing.

[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     } } 

This is as safe as the using statement in an individual test because NUnit will guarantee that TearDown is called.

Having said all that I do think that tests that hit the database are not really unit tests. I still write them, but I think of them as integration tests. I still see them as providing value. One place I use them often is in testing LINQ to SQL code. I don't use the designer. I hand write the DTO's and attributes. I've been known to get it wrong. The integration tests help catch my mistake.

like image 83
Mike Two Avatar answered Sep 23 '22 07:09

Mike Two