Question

In this asp.net I'm cleaning up it's possible for deadlocks to occur. I want to make sure that the code deals with them properly, so I'm trying to write NUnit tests which trigger a deadlock.....

The DAO is split by entity. Each entity has a set of tests which are surrounded by Startup() and Teardown() methods which create a transactionscope and then roll it back after the tests are complete. This works great for everything else, but is completely useless for deadlocks.

How can I setup and run a "deadlock" test using TransactionScope and SQL2000 (ie MSDTC is involved) that can be reliably reproduced? More detail: I know there is a situation whereby if two users call two functions with different, specific, data values then a deadlock can result. How can I simulate this within NUNIT - and make the deadlock always happen?

And yes, I did start with the "Why don't you stop the deadlocks happening in the first place" plan of action, but I have no control over the code where the deadlocks can occur - I just call the functions and they can deadlock.

Was it helpful?

Solution

If your deadlock results in an exception being thrown, you want to use a Mock Object to emulate the exception being thrown.

The basic idea is that you tell your Mock Object framework (I like TypeMock) to throw an exception instead, something like this:

MockObject mo = MockManager.MockObject(typeof(MyDeadlockException));
mock.ExpectAndThrow("MyMethod", (MyDeadlockException)mo.Object); 

The idea is basically the same for other mocking frameworks.

OTHER TIPS

Most of these solutions involve multiple threads. Here is one that does not.

Close these Loopholes - Reproduce Database Errors

The author is Alex Kuznetsov.

What if one of your tests in the middle of your transaction just does a "wait" for like 5 minutes? Or, you simply write a test that starts a transaction, creates a new record, and then updates that record without committing. Then, start a new transaction in and try to read that record that was created and is currently being updated. You'll get a deadlock there.

What if you manually locked a table and ALWAYS left it locked? Then, any action you took against that table would produce a deadlock situation?

Coming at this blind, but is it possible to in your TestSetup method to actually create a SQLConnection to your database? Then, using that, you could just issue either a command to lock the table or take some action to lock a record or page? That way it would be outside of any other transactions you've got going on? It seems like this would be an option you've already considered though. What am I missing about your situation?

For unit testing you probably want to avoid actually using a database. How do you know you have a deadlock. You should be testing the condition that tells you there is a deadlock and creating that in your test.

A mock is an ideal whay to mimic that if you call a service and it returns an error. Simply have the mock return the error you are expecting. If you are waiting for a timeout or something then the same thing applies.

In general a unit test should only run on the code being tested and not rely on any other code or components. That said - databases are essentially another component and you are probably doing some sort of functional tests using nunit to drive them.

In that case you really have to create a deadlock situation but locking a record, or table and then calling a component that tries to use the same record and handling the response.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top