Transaction Timeout When Using the RollBack Attribute

I noticed a recent check-in has added a TimeOut property to the RollBack attribute in MbUnit. Woohoo!

A while ago I presented the source code for a RollBack attribute for NUnit based on Roy Osherove’s work in the area. Well I found a little problem with using the RollBack attribute that affects the one I presented along with the one that comes packaged with MbUnit.

I uncovered the problem while running a particularly long running unit test. Every time I ran the test, it failed at just about exactly 61 seconds into it (I know, a unit taking that long is kind of useless for TDD, but I’ll get that time down to something manageable. I promise!).

I reran the test multiple times and the line of code it failed on would be different, but MbUnit was showing me that it was failing at 61 seconds every time. To prove it, I removed the RollBack attribute and ran the test and it succeeded after around 90 seconds (yeah, I have some heavy perf work to do, but it is a BIG test).

The error message I got each time was Distributed transaction completed. Either enlist this session in a new transaction or the NULL transaction.

Not a helpful message because I wasn’t attempting to complete the transaction. But the timing of the matter made it obvious to me I was running into a timeout issue.

The RollBack attribute works by enlisting a COM+ 1.5 transaction, which allows you to use Enterprise Services without inheriting from ServicedComponent using a feature called Services Without Components or SWC for short (gotta love them TLAs). To work around the issue in MbUnit, I simply removed the RollBack attribute and added the code to start a COM+ transaction directly to the method. The one change I made was to set the TransactionTimeout property which takes an integer timeout value in seconds.

[Test]

public void MyTest()

{

    ServiceConfig config = new ServiceConfig();

    config.TransactionTimeout = 120;

    config.Transaction = TransactionOption.RequiresNew;

    ServiceDomain.Enter(config);

    try

    {

        //Run my test code...

    }

    finally

    {

        if(ContextUtil.IsInTransaction)

        {

            //Abort the transaction.

            ContextUtil.SetAbort();

        }

        ServiceDomain.Leave();

    }

}

At the same time, I revisited the RollBack attribute I put together for NUnit and added a TransactionTimeout property to the attribute. That way you can mark up a test like so...

[Test]

[RollBack(120)]

public void MyTest()

{

    //Run my test code...

}

You can download the new version of the attribute for NUnit here.

As for MbUnit, I’ll mention this to the maintainers and we’ll hopefully see a fix soon.

What others have said

Requesting Gravatar... JIRA: MbUnit Oct 19, 2005 8:51 PM
# [MBUNIT-16] RollBack attribute doesn't allow specifying a TransactionTimeout
I wrote this up here...

I need a way to specify a larger timeout for the com+ transaction than the default...
http://haacked.com/archive/2005/10/19/10879.aspx MbUnit 2.22.00
Requesting Gravatar... Jonathan de Halleux Oct 20, 2005 10:43 PM
# re: Transaction Timeout When Using the RollBack Attribute
Phil,

MbUnit is extendible, i.e. you could write your own Rollback attribute and use in your project *without* recompilation of MbUnit.

Cheers,
Peli
Requesting Gravatar... Haacked Oct 20, 2005 10:56 PM
# re: Transaction Timeout When Using the RollBack Attribute
True. But I still want to see the main codebase get updated. I have a workaround for now. I'll probably add that at some point.
Requesting Gravatar... JIRA: MbUnit Dec 06, 2006 9:45 AM
# [MBUNIT-16] RollBack attribute doesn't allow specifying a TransactionTimeout
I wrote this up here... <br /><br />I need a way to specify a larger timeout for the com+ transaction than the default...<br />http://haacked.com/archive/2005/10/19/10879.aspx MbUnit 2.22.00

What do you have to say?

(will show your gravatar)
Please add 8 and 3 and type the answer here: