Archive for June, 2007

Integration Tests with NHibernate

4 commentsWritten on June 22nd, 2007 by
Categories: NHibernate, Software Development, testing

In my last post i experimented with a way to run my integration tests without polluting my database. I created a specific TransactionFactory which NHibernate would use to create transactions whenever they were requested. My factory returned a transaction which would actually rollback the transaction, instead of committing it. This way, the transactions were not committed during test runs, and the code being tested did not have to be changed. It works, but it gets messy very quickly if an integration test would call multiple methods that were transactional. The test transaction would have to stay alive during the entire test, and would have to be reused by all the transactional methods called in that test, all without changing the code being tested. It's doable, but i didn't feel too good about it.

I looked for other options and i believe i've found a pretty good one. It would be great if i could somehow wrap every data access call caused by a test into one MS DTC transaction. Then, after the test i'd simply have to abort the MS DTC transaction. The database stays clean, the tests remain independent of what may already be in the database and most importantly, i wouldn't have to change my production code.

So, what do i need here? First i need a way to connect an NHibernate session to the current DTC transaction. And i also need a custom TransactionFactory for NHibernate to use which will return dummy transaction objects which do nothing. The production code will receive these transaction dummies whenever a transaction is requested and will call Commit() on them when needed. Obviously, the Commit() implementation of my dummy transaction is a no-op.

Let's start with connecting an NHibernate session to a DTC transaction. NHibernate provides access to the underlying database connection through the ISession.Connection property which returns an IDbConnection. Most objects that implement IDbConnection have an EnlistDistributedTransaction() method, which does exactly what we want, but it's not defined in the IDbConnection interface. The only one that doesn't have this method as far as i know, is the implementation in the System.Data.SqlServerCe namespace. I don't use SqlServerCe so that's not a problem for me.

I want my production code to request NHibernate sessions through my own provider which implements the following interface:

public interface ISessionProvider
{
  public ISession GetNewSession();
}

At runtime, the real SessionProvider will be used which will provide NHibernate sessions which use the default AdoNetTransactionFactory and AdoTransactions. At unit-test time, the following ISessionProvider will be used:

public class SessionUsingDtcProvider : ISessionProvider
{
  private ISessionFactory _sessionFactory = null;

  private ISessionFactory SessionFactory
  {
    get
    {
      if (_sessionFactory == null)
      {
        NHibernate.Cfg.Configuration configuration =
           new NHibernate.Cfg.Configuration()
              .AddAssembly("MyMappingAssembly");

        ISessionFactory sessionFactory =
           configuration.BuildSessionFactory();

        // overwrite the NHibernate TransactionFactory so it will use our
        // own factory. check the previous post if you don't know why
        // i do it this way
        PropertyInfo propertyInfo = sessionFactory.Settings.GetType()
            .GetProperty("TransactionFactory");
        propertyInfo.SetValue(sessionFactory.Settings,
             new TestTransactionFactory(), null);
      }

      return _sessionFactory;
    }
  }

  public ISession GetNewSession()
  {
    ISession session = SessionFactory.OpenSession();
    EnlistInDtcTransaction(session.Connection);
    return session;
  }

  private void EnlistInDtcTransaction(IDbConnection connection)
  {
    MethodInfo methodInfo = connection.GetType()
       .GetMethod("EnlistDistributedTransaction",
          BindingFlags.Public | BindingFlags.Instance);

    methodInfo.Invoke(connection, new object[]
      { (System.EnterpriseServices.ITransaction)
           ContextUtil.Transaction
      });
  }
}

So the EnlistDistributedTransaction() method is called through reflection because it's not defined in the interface. I wouldn't do this for production code, but for test-code i think it's OK.

The TestTransactionFactory class looks like this:

public class TestTransactionFactory : ITransactionFactory
{
  public void Configure(System.Collections.IDictionary props)
  {
  }

  public ITransaction CreateTransaction(ISessionImplementor session)
  {
    return new TestTransaction();
  }
}

And the TestTransaction is as dumb as it possibly could be:

public class TestTransaction : ITransaction
{
  public void Begin(System.Data.IsolationLevel isolationLevel)
  {
  }

  public void Begin()
  {
  }

  public void Commit()
  {
  }

  public void Enlist(System.Data.IDbCommand command)
  {
  }

  public bool IsActive
  {
    get { return true; }
  }

  public void Rollback()
  {
  }

  public bool WasCommitted
  {
    get { return false; }
  }

  public bool WasRolledBack
  {
    get { return false; }
  }

  public void Dispose()
  {
  }
}

Now suppose you have the following code in your business layer:

public class CustomerService
{
  private ISessionProvider _sessionProvider;

  public CustomerService(ISessionProvider sessionProvider)
  {
    _sessionProvider = sessionProvider;
  }

  public void SaveCustomer(Customer customer)
  {
    using (ISession session = _sessionProvider.GetNewSession())
    using (ITransaction transaction = session.BeginTransaction())
    {
      session.SaveOrUpdate(customer);
      session.Flush();
      transaction.Commit();
    }
  }
}

As you can see, this code requests a transaction and commits the transaction after the data is inserted or updated in the database. At runtime, this is exactly what i want. But during my tests, i don't want this to actually be commited.

So now i could test this without polluting my database like this:

[TestClass]
public class MyTestClass
{
  [TestInitialize]
  public void TestInitialize()
  {
    SetUpDtcTransaction();
  }

  private void SetUpDtcTransaction()
  {
    ServiceConfig serviceConfig = new ServiceConfig();
    serviceConfig.Transaction = TransactionOption.RequiresNew;
    ServiceDomain.Enter(serviceConfig);
    ContextUtil.MyTransactionVote = TransactionVote.Commit;
  }

  [TestCleanup]
  public void TestCleanup()
  {
    AbortDtcTransaction();
  }

  private void AbortDtcTransaction()
  {
    ContextUtil.MyTransactionVote = TransactionVote.Abort;
    ServiceDomain.Leave();
  }

  [TestMethod]
  public void TestSaveCustomer()
  {
    CustomerService service =
       new CustomerService(new SessionUsingDtcProvider());

    Customer customer = new Customer();
    customer.Name = "Davy Brion";

    service.SaveCustomer(customer);

    Assert.IsTrue(customer.Id > 0);
  }
}

Mission accomplished :)

Note: this test instantiates the SessionUsingDtcProvider which will create the NHibernate SessionFactory which is a rather expensive operation... In your production code, the correct SessionProvider should only be created once and made available so the rest of the code has easy access to it.

Update: it's no longer necessary to set NHibernate's TransactionFactory through reflection. Read this...

NHibernate ignores hibernate.transaction_factory setting

4 commentsWritten on June 21st, 2007 by
Categories: NHibernate, Software Development

I want to be able to run my integration tests in their normal setup, but at the same time I don't want the database actions caused by my tests to be committed to the database. And since my business layer manages the transactions (and thus, calls Commit() on them) i needed a way to make sure that those Commit() calls wouldn't actually commit to the database when the code was executed by the integration tests.

Luckily, NHibernate offers a configuration option (hibernate.transaction_factory) where you can specify which ITransactionFactory type should be used at runtime. Excellent! I could just tell NHibernate to use my specific TestTransactionFactory which would keep returning the same TestTransaction during the execution of a single test. The TestTransaction would silently ignore calls to Commit() and rollback automatically when it is closed or goes out of scope.

Granted, there are probably much cleaner ways to achieve this, but at the moment i can't think of a better way. So if you know a cleaner way, by all means consider this post an extensive brainfart and please post the preferred solution :)

Until then, let's continue...

So, I created my TestTransactionFactory which implements the ITransactionFactory interface and i let it return a cached instance of TestTransaction whenever a transaction is requested. A TestTransaction instance simply wraps an NHibernate.Transaction.AdoTransaction object but ignores calls to Commit() and automatically rolls back the transaction when it is closed or goes out of scope. Then, i set the hibernate.transaction_factory setting in my config file to my own factory.

And this is the test:

[TestMethod]
public void TestFakeTransactionRollsBackInsteadOfCommit()
{
  using (ISession session = SessionProvider.GetNewSession())
  {
    ITransaction transaction = session.BeginTransaction();

transaction.Commit();
transaction.Dispose();

Assert.IsTrue(transaction.WasRolledBack);

} }

So i ran the test once i told NHibernate to use my own factory... but it failed. NHibernate was still using an AdoNetTransactionFactory. After making sure i didn't screw up, i looked in the NHibernate source code (yay for open source!) to find where the transactionfactory was created and found this:

ITransactionFactory transactionFactory = new AdoNetTransactionFactory();

Simply inexcusable... They provide the interface and the configuration option, and then they completely ignore it. After swearing loudly for a few moments, i decided to just overwrite the transactionfactory using reflection.

So now, my test looks like this:

[TestMethod]
public void TestFakeTransactionRollsBackInsteadOfCommit()
{
  using (ISession session = SessionProvider.GetNewSession())
  {
    ITransactionFactory originalTransactionFactory =
      session.SessionFactory.Settings.TransactionFactory;

PropertyInfo propertyInfo = session.SessionFactory.Settings.GetType()
  .GetProperty("TransactionFactory");
propertyInfo.SetValue(session.SessionFactory.Settings,
  new TestTransactionFactory(), null);

ITransaction transaction = session.BeginTransaction();

transaction.Commit();
transaction.Dispose();

Assert.IsTrue(transaction.WasRolledBack);

propertyInfo.SetValue(session.SessionFactory.Settings,
  originalTransactionFactory, null);

} }

And it works. I would like to point out that i'd never do this in production code, but for the sake of keeping my database clean while running my integration tests i think this is acceptable.

Update: this issue has been fixed

Introduction to the upcoming ADO.NET Entity Framework

No Comments »Written on June 17th, 2007 by
Categories: Entity Framework

John Papa posted a nice introduction to Entity Framework. If you're new to Entity Framework (like me) then it's definitely a good read.

One thing i already dislike about EF is that it uses 3 kind of mapping files:

  • Conceptual Schema Definition Language (CSDL) to define your domain entities
  • Store Schema Definition Language (SSDL) to define your database tables
  • Mapping Schema Language which contains the actual mappings between the domain entities and the database structure

This really seems excessive. With NHibernate, all of this information is stored in one mapping layer. You might argue that it is conceptually cleaner to split up all of this information, but for now it seems rather impractical to me.

I hope they change this before the final version is released.

Other than the mappings, it looks pretty nice. And they already announced that the final version will support Persistance Independence so it should get even better :)

Back from (N)hibernation

No Comments »Written on June 17th, 2007 by
Categories: About The Blog

I haven't posted anything in a while, but recently i've been playing around with NHibernate which sparked my interest in playing around with .NET again. A little over a year ago i sold my windows laptop which only left me with my iMac G5. The G5 chip is a PowerPC chip which ment i couldn't run Windows on it. No biggie, i thought. I disliked Windows anyway, and i was already using .NET at work all day so i figured i'd be fine. So at home, i switched to Java to scratch my coding itch.

Now, i think Java is a very nice language and i enjoyed writing a new IrcLeech version in it. But once i got IrcLeech working in Java, i never really found something else i wanted to do in it. So then i started playing around with Objective C and Cocoa to do some native OS X programming. And while those technologies are very cool, i didn't really find something cool i wanted to work on.

So about 2 weeks ago, i was finally able to play with NHibernate in a little experiment at work. I like the technology so much i really want to get involved with the project, and some other projects as well. So... i ordered a new Macbook so i'll still have OS X, but now i'll be able to run Visual Studio in a parallels desktop session alongside my OS X session. So once the laptop arrives, i plan on getting very familiar with the inner workings of nhibernate and perhaps even contribute to the project. There are some other projects i really wanna play with as well, such as Castle's DynamicProxy, Castle's ActiveRecord, Ayende's Rhino Mocks and several more. Should be a lot of interesting stuff :)

Programming Languages Don’t Matter

2 commentsWritten on June 17th, 2007 by
Categories: Rants

Note: this was originally written on August 28, 2006

Programming languages have been the topic of endless discussions for years now, and a lot of people take these things very seriously. Well, a lot of developers take these things very seriously. Normal people don't care, and boy are they right. Some developers will stick with a certain language purely for syntactical reasons. And some will dislike a language because of its syntax even though the language itself might be extremely powerful. Other developers prefer languages which mainly provide improved productivity, even though the syntax might not be as elegant or even cool. And let's not forget the developers who choose a language based solely on how many jobs are available for that language.

I've only been working as a software developer for 4 years, but i've been writing code for the last 10 years. During those years i've written code in C, C++, Visual Basic, C# and Java. I've played around with other languages as well, but not enough to actually count them among the languages i've done anything more than trivial stuff in. One of the most important things i've learned is that the language simply doesn't matter. A language can make some things easy, and some things hard. But in the end, the language is just a tool to help you write your code. The way you design and write your code should be done independently of the language you use.

I've always said that coding is like talking. Once you've learned to talk, you can learn any language to express your thoughts and feelings. It's the same thing with coding. At least, it should be. Once you've learned to code, you should be able to write code in any language they throw at you. It's just a matter of learning the syntax. The tricky part is that some languages will try to push you into certain directions that may or may not be the right path for you to take. Visual Basic is a prime example of this. Visual Basic tries to persuade you to take certain shortcuts. Shortcuts that lead to sloppy, ugly and even unmaintainable code. But it will be easy to write. At least, that's what they (and i'm pointing at Microsoft here) want you to think. In reality this easy code will be your worst nightmare once you have to maintain the code over a long period of time. But does that mean that Visual Basic is an inferiour language? A language so bad it's impossible to write good code in? No. A good developer will write good code in Visual Basic. Because a good developer knows how to write code 'into' a language, instead of 'in' a language.

Programming into your language, instead of in it is a concept that is explained in the classic software development book Code Complete by Steve McConnell. It basically means that as a developer, you should think of what you need to do, and how you want to do it, and then assess how to do that in the language you are using. If that's how you approach writing code, you are programming into your language. But most developers let their language and environment dictate the way they write their code. These developers are programming in their language. And they're gonna have a hard time when they're forced to move to a new language. Do yourself a favor and stay away from these developers. If you're hiring people, skip these developers. They may even be highly proficient in their current language but if they can't think about code outside of their language, they will be a burden on your team once you switch languages in your company.

Knowing the ins and outs of your programming language is very helpful, but i'd never judge a developer based on his/her knowledge of obscure language features. There's a reason why these things are obscure. Instead, focus on concepts, good programming practices and depending on the ambition of the developer, design patterns. These are the things that make a difference between a good developer, and a not so good developer.