Using System.Transactions.TransactionScope to ensure no permenant DB changes from Unit Tests.  
Author Message
KevinBuchan





PostPosted: Visual Studio Performance Tools (Profiler), Using System.Transactions.TransactionScope to ensure no permenant DB changes from Unit Tests. Top

For many reasons, I have written a tool to generate Data Access Layer classes, in addition to other basic plumbing for applications. My tool also generates Unit Test classes to validate the properties, methods, and constructors.

Of course one of the most important sets of method types I need to validate are the ones that actually persist record creations, updates, and deletes to the back end data store (MS SQL Server 2005).

I had hoped to be able to create an instance of a System.Transactions.TransactionScope object in my "MyClassInitialize" method with the <ClassInitialize()> attribute. I get no errors instantiating it, but I get errors of the following type when my test run completes:

Class Cleanup method ContactTest.MyClassCleanup failed.
Error Message: System.InvalidOperationException: A TransactionScope must be disposed on the same thread that it was created.. Stack Trace: ...

I want to be able to do all my database changes in a sandbox and feel certain that I won't goof anything up.

I looked through this forum, but didn't see a post specifically about this type of issue and its resolution.

Thanks!




Visual Studio Team System25  
 
 
T.N. Arvind





PostPosted: Visual Studio Performance Tools (Profiler), Using System.Transactions.TransactionScope to ensure no permenant DB changes from Unit Tests. Top

Hi,

You shouldn't create the instance at class level. Use the TransactionScope within your TestMethod

[TestMethod()]

[ExpectedException(typeof(YourException))]

public void YourTestMethod()

{

TransactionOptions options = new TransactionOptions();

options.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;

options.Timeout = new TimeSpan(0, 2, 0);

TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, options);

using(scope)

{

objectA.MethodYouWantToTest(); // Create an instance of your class in ClassInitialize

}

// scope is automatically set to null and hence cannot be used again

}

repeat the above process for each and every TestMethod.

Regards

Arvind T N



 
 
KevinBuchan





PostPosted: Visual Studio Performance Tools (Profiler), Using System.Transactions.TransactionScope to ensure no permenant DB changes from Unit Tests. Top

Well, I got this to work, but it was much harder than I thought it should be.

First off, I moved the TransactionScope management code into the "<TestInitialize()> Public Sub MyTestInitialize()" and "TestCleanup()> Public Sub MyTestCleanup()" methods.

Next, I read several blogs discussing the errors I was receiving and learned that I had to do the following:

Steps:
1) Open Component Services
2) Right click on "My Computer" and view Properties
3) Select the "MTDTC" tab.
4) Click the button labeled 'Security Configuration'.
5) Check:
Network DTC Access
Allow Outbound
6) Save settings.


Open Windows Firewall
Add "c:\WINDOWS\system32\msdtc.exe" to the exceptions list.

Turns out the biggest problems were not related to the code at all.