Unit Testing DAL Migration from Enterprise Library to Linq-to-Sql

I recently revived a project I wrote a few years ago.  In addition to adding new features I also wanted to update the existing data access code to no longer use the Enterprise Library, but instead LINQ-to-SQL.

Getting Started

In order to make sure I didn’t break any existing functionality I used unit tests (MS Test) to compare the existing and ported code.

[TestMethod]
public void SelectFoos_Present_ResultsMatch()
{
    Assert.Fail();
}

Setup

With this test in place copied FooDAL to a new directory in the DataAccessLayer namepsace called Linq.  I then swapped out the base class containing the Enterprise Library factory code with a new LinqDal class that contained my FooBarDataContext.  In my new Linq-to-SQL dbml file I mapped the Foo table and the Foo_Select stored procedure, setting the return type to the class for the table.

The main focus was making sure the results were identical between the two implementations.  The risk would only increase as I went through and refactored the code base.

Revision 1


[TestMethod]
public void SelectFoos_Present_ResultsMatch()
{
    var entDal = new FooDAL();
    var entResults = entDal.SelectFoos();

    var linqDal = new Linq.FooDAL();
    var linqResults = linqDal.SelectFoos();

    // ... compare
    Assert.Fail();
}

Comparing Results

In order to compare the results I deferred to my trusty copy of More Effective C# by Bill Wagner.

using (var firstSequence = entResults.GetEnumerator())
using (var secondSequence = linqResults.GetEnumerator())
{
    while (firstSequence.MoveNext() && secondSequence.MoveNext())
    {
        var firstItem = firstSequence.Current;
        var secondItem = secondSequence.Current;

        Assert.AreEqual(
            firstItem.FooID, 
            secondItem.FooID, 
            firstItem.FooID + " - " + secondItem.FoodID);
    }
}

This made sure the sequencing of the objects was the same, but what about making sure the objects were correctly populated?

EqualityComparer

I didn’t want to mess around with the existing business class that is returned by the DAL method so instead I used another tip from Bill Wagner’s book; EqualityComparer.

private class FooComparer : EqualityComparer<FooBLL>
{
    public override bool Equals(FooBLL x, FooBLL y)
    {
      	return x.FooID.Equals(y.FooID) &&
            	x.Name.Equals(y.Name);
    }

    public override int GetHashCode(FooBLL obj)
    {
      	return EqualityComparer<FooBLL>.Default.GetHashCode(obj);
    }
}

Final Revision

With this in place I could factor out the comparing logic into a separate method in a base class and reuse it for the different DAL classes I had to migrate. The final test looks like this:

[TestMethod]
public void SelectFoos_Present_ResultsMatch()
{
    var entResults = new FooDAL().SelectFoos();
    var linqResults = new Linq.FooDAL().SelectFoos();
            
    this.CompareLists<FooBLL>(entResults, linqResults, 
        new FooComparer());
}

// in Test base class
public void CompareLists<T>(IEnumerable<T> first, IEnumerable<T> second, 
    EqualityComparer<T> comparer)
{
    using (var firstSequence = first.GetEnumerator())
    using (var secondSequence = second.GetEnumerator())
    {
        while (firstSequence.MoveNext() && secondSequence.MoveNext())
        {
            var firstItem = firstSequence.Current;
            var secondItem = secondSequence.Current;

            Assert.IsTrue(comparer.Equals(firstItem, secondItem));
        }
    }
}

Closing Thoughts

I refactored 7 DAL classes using this and I feel pretty confident the results are exactly the same. I did run into some cases where writing the tests did reveal discrepancies in the results so I feel it was time well spent.

The only change I made looking back was overloading the ToString method on FooBLL so I could see what the differences were in the test results. The message for the Assert called ToString on the objects giving me an xml visualization of the class so I can track down the error.

public override string ToString()
{
    var serializer = new 
        System.Xml.Serialization.XmlSerializer(this.GetType());
    var writer = new System.IO.StringWriter();
    
    serializer.Serialize(writer, this);
    return writer.ToString();
}

One Response to “Unit Testing DAL Migration from Enterprise Library to Linq-to-Sql”

  1. [...] Blogosphere Just another WordPress.com weblog « Unit Testing DAL Migration from Enterprise Library to Linq-to-Sql [...]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.