We have some NUnit tests that access the database. When one of them fails it can leave database in inconsistent state - which is not an issue, since we rebuild database for
I'm not saying this is a great idea, but it should work. Remember that assertion failures are just exceptions. Also don't forget there is also a [TestFixtureTearDown] attribute that runs just once after all tests in the fixture have run.
Using those two facts you can write something like setting a flag if a tests failed and checking the value of the flag in the test fixture tear down.
I don't recommend this, but it would work. You aren't really using NUnit as intended, but you can do it.
[TestFixture]
public class Tests {
private bool testsFailed = false;
[Test]
public void ATest() {
try {
DoSomething();
Assert.AreEqual(....);
} catch {
testFailed = true;
}
}
[TestFixtureTearDown]
public void CleanUp() {
if (testsFailed) {
DoCleanup();
}
}
}
What about using a Try-Catch block, rethrowing the exception caught?
try
{
//Some assertion
}
catch
{
CleanUpMethod();
throw;
}
One option not mentioned so far is to wrap the test up in a TransactionScope object, so it doesn't matter what happens as the test never commits anything to the DB.
Here's some details on the technique. You can probably find more if you do a search on unit testing and transactionscope (though you are really doing integration testing if you hit a DB). I've used it successfully in the past.
This approach is simple, does not require any cleanup and ensures that tests are isolated.
Edit- I've just noticed Ray Hayes answer is also similar to mine.
Whilst it might be possible to coerce nUnit into doing this it isn't the most sensible design, you could always set a temporary file somewhere and if that file exists, run your cleanup.
I would recommend changing your code so that you have database-transactions enabled and at the end of the test, simply revert the database to the original state (e.g. discard the transaction that represents your unit-tests).
I would do like phsr suggests for now and when you can afford it, refactor the tests so that they never have to rely on the same data that another test needs or even better abstract the data access layer and mock the results coming from that database. It sounds like your tests are rather expensive and you you should do all your query logic on the database and business logic in your assembly you don't really care what the results are that are returned.
You will also be able to test your ExceptionHandling a lot better.
You can add a [TearDown]
method with
if (TestContext.CurrentContext.Result.Status != TestStatus.Passed)
some code to be executed if test failed.