These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: Tip: Non-destructive unit tests in .Net 2.0
PostPosted: Fri Jun 23, 2006 12:16 am 
Regular
Regular

Joined: Wed Jun 21, 2006 3:13 pm
Posts: 110
I wanted a way to easily guard my database-specific unit tests. Using the new System.Transactions namespace and ADO.NET's auto-enlist features did the trick. Note, this has only been tested against SQL Server 2000 and needs DTC in that scenario. This should easily work with SQL Server 2005 through the lightweight transaction manager as well (2005 defers promoting transactions as long as possible, relying on the LTM instead).

Code:
public class TransactionalTest
{
  public TransactionalTest()
  {
    Transaction.Current = new CommittableTransaction(); 
  }
      
  ~TransactionalTest()
  {
    if (Transaction.Current != null && Transaction.Current.TransactionInformation.Status != TransactionStatus.Committed)
      Transaction.Current.Rollback();
  }
}


My test code then looks like:
Code:
[TestFixture]
public class AccountTest : TransactionalTest
{
  [Test]
  public void CreateAccount()
  {
    Account user = new Account();
    user.Username = "test";
    user.Password = "test";
     
    Role adminRole = Role.Get(1);
    user.Roles.Add(adminRole);

    user.Save();
     
    Assert.IsTrue(user.Id > 0);
    Assert.IsTrue(user.Version == 1);
  }
}


The user.Save() function, effectively, looks like this:
Code:
BeginTransaction();
Session.SaveOrUpdate(o);
CommitTransaction();


With the call to begin and commit transaction being convenience wrappers for session.begintransaction and session.committransaction.

If you run your test with show_sql=true, you'll notice that the SQL does execute and no errors are thrown. You should be able to verify that no data is saved in the database.

If you absolutely wanted to force a save to the database in a specific instance, but still extend this base class for all other tests in given suite, then you could run this:
Code:
[TestFixture]
public class AccountTest : TransactionalTest
{
  [Test]
  public void CreateAccount()
  {
    Account user = new Account();
    user.Username = "test";
    user.Password = "test";
     
    Role adminRole = Role.Get(1);
    user.Roles.Add(adminRole);

    user.Save();

    ((CommittableTransaction)Transaction.Current).Commit();
     
    Assert.IsTrue(user.Id > 0);
    Assert.IsTrue(user.Version == 1);
  }
}


Known limitations: I haven't tested this against any other platforms yet. I'm still new to the whole System.Transactions namespace so I'm not quite sure what the model would look like against, say, MySQL. I'm guessing it'd try and promote to the DTC as well, but that's just a hunch. Additionally, if you are trying to run your test against a remote 2000 SQL Server, the DTC is set to refuse remote connections by default with the SP4 install. You'll receive a very clear error message to this effect as well. Set the DTC on the remote box to allow remote clients and you'll be good to go.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.