Archive for the ‘TDD’ Category

Mocking LightSpeed Units Of Work

Tuesday, May 12th, 2009

One of my colleagues asked me the other day how he could mock a LightSpeed UnitOfWork. Apparently he couldn’t find any good examples out there on the InterWeb so I thought I’d post this short code sample to show how its done.

The most important thing is that you should not create your UnitOfWork yourself but use the CreateUnitOfWork() factory method on your LightSpeedContext. See code example below.

using (var unitOfWork = Repository.Context.CreateUnitOfWork())
 {
        var customerOverEighteenYearsOld = unitOfWork
                              .Customers
                              .Where(customer => customer.Age > 18);
       return customerOverEighteenYearsOld.ToList();
 }

Now if we wanted to test this code by mocking our UnitOfWork we can substitute our IQueryable<Customers> with an in memory collection rather than hitting the database directly.

So our unit test setup code would look something like this. The example below uses Rhino Mocks to mock the Unit Of Work.

[SetUp]
public void TestSetUp()
{
         // Customer Collection
         var customers = new List<Customer>{
                                new Customer{Age = 10},
                                new Customer{Age = 18}
                                }; 

         var unitOfWorkFactory = MockRepository.GenerateStub<IUnitOfWorkFactory>();
         var unitOfWork = MockRepository.GenerateStub<CustomersUnitOfWork>(); 

         // Replace the normal UnitOfWorkFactory with our implementation.
         Repository.Context.UnitOfWorkFactory = _unitOfWorkFactory; 

         // Stub the behaviour of our unit of work factory to
         // return our mocked UnitOfWork
         unitOfWorkFactory
                    .Stub(uowf => uowf.Create(Arg<LightSpeedContext>.Is.Anything))
                    .Return(unitOfWork ); 

         // Stub our unit of work to return our in memory customer collection.
         unitOfWork.Stub(uow => uow.Customers()).Return(customers);
}

So all we really need to do is to mock our LightSpeed UnitOfWork Factory replacing the default factory on our LightSpeed Context with our mocked version.  

We can then stub out the Create method on our mocked UnitOfWork factory to return our own implementation of our UnitOfWork (which is also a mock).  

We can now get our UnitOfWork to behave as we want it to without ever having to hit a database.

kick it on DotNetKicks.com

Unit Testing LightSpeed Entities

Thursday, April 2nd, 2009

If you have not heard of LightSpeed or had a play with it then you should check out the excellent lightweight ORM from the boys at Mindscape.  I have worked with it for a couple of years now and really like it for certain type of projects, I think its simplicity is a good stepping stone for developers making that transition from old data access strategies to ORM technologies.

The one thing I don’t like about it is that your domain objects are not persistant ignorant of the underlying ORM technology, and have to inherit from an Entity base class.

I have run into problems when trying to unit test code that use my Lightspeed entities because I cannot just create a new entity without hitting the database.  Normally when you request an entity from the database the construction of that entity is handled by the Lighspeed framework.

Some of the things that were causing me problems were:

  • I could not assign my own Id for the entity.
  • The Entities throw an exception if they don’t have UnitOfWork set.
  • Could not set up EntityCollection relationships between domain objects as they are read only properties.

In the end I created a LightSpeedEntityFactory and some helper methods for testing purposes to create my entities and get around some of these issues.  I hope you find the following code useful.

    ///

    /// Factory class for building LightSpeedEntity, that are are divorced from a real UnitOfWork.
    /// 

    /// To be used for Unit Testing purposes only!
    internal class LightSpeedEntityFactory
    {
        #region Methods

        ///

        /// Build a LighSpeed Entity with the chosen Id, and a Fake UnitOfWork.
        /// 

        /// 
        /// 
        public static T Build<T>(object id) where T : Entity
        {
            var lightSpeedEntity = Build<T>();

            lightSpeedEntity.SetId(id);

            return lightSpeedEntity;
        }

        ///

        /// Build a LighSpeed Entity with a Fake UnitOfWork.
        /// 

        /// 
        /// 
        public static T Build<T>() where T : Entity
        {
            var lightSpeedEntity = (T)Activator.CreateInstance(typeof (T));

            IUnitOfWork unitOfWork = new UnitOfWork();

            lightSpeedEntity.SetUnitOfWork(unitOfWork);

            return lightSpeedEntity;
        }

        #endregion Methods
    }
   ///

    /// Some helper extension methods for changing the internals of a LightSpeed entity.
    /// 

    /// 
    /// We do some very naughty stuff in here using reflection and these methods
    ///  should only be used for the purposes of Unit Testing.
    /// 
    public static class LightSpeedHelper
    {
        #region Methods

        ///

        /// Set the Id of a LightSpeed Entity. This is usually only a read-accessible property.
        /// 

        public static void SetId(this Entity entity, object id)
        {
            var setIdInternalMethod = entity.GetType().GetMethod("SetIdInternal", BindingFlags.NonPublic | BindingFlags.Instance);

            setIdInternalMethod.Invoke(entity, new[] {id});
        }

        ///

        /// Sets a read-only property on a LightSpeed Entity.
        /// For setting up an object for testing purposes only.
        /// 

        /// lightspeedEntity.SetProperty(a => a.Addresses).SetValue(addresses)
        /// 
        /// The type of the ESULT.
        /// 
        public static IPropertySetter<RESULT> SetProperty<T, RESULT>(this T entity, Expression<Func<T, RESULT>> action) where T : Entity
        {
            var outerMember = (MemberExpression)action.Body;

            var outerProp = (PropertyInfo)outerMember.Member;

            var propertyName = outerProp.Name;

            IPropertySetter<RESULT> propertySetter = new PropertySetter<RESULT>(entity, propertyName);

            return propertySetter;
        }

        ///

        /// Sets the unit of work on a LighSpeed Entity.
        /// 

        public static void SetUnitOfWork(this Entity entity, IUnitOfWork unitOfWork)
        {
            var uowProperty = entity.GetType().GetProperty("UnitOfWork", BindingFlags.NonPublic | BindingFlags.Instance);

            uowProperty.SetValue(entity, unitOfWork, null);
        }

        #endregion Methods
    }
    public class PropertySetter<T> : IPropertySetter<T>
    {
        #region Fields

        private readonly object _parent;
        private readonly string _propertyName;

        #endregion Fields

        #region Constructors

        public PropertySetter(object parent, string propertyName)
        {
            _parent = parent;
            _propertyName = propertyName;
        }

        #endregion Constructors

        #region Methods

        public void SetValue(T value)
        {
            var fieldName = FormatPropertyName(_propertyName);

            var fieldInfo = _parent.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);

            fieldInfo.SetValue(_parent, value);
        }

        private static string FormatPropertyName(string propertyName)
        {
            // get the first letter of the property name.
            var sb = new StringBuilder();

            sb.Append("_");
            sb.Append(char.ToLower(propertyName[0]));
            sb.Append(propertyName.Substring(1));

            return sb.ToString();
        }

        #endregion Methods
    }

UPDATE – ADDED CODE FOR IPROPERTY SETTER THAT WAS MISSING

    public interface IPropertySetter<T>
    {
        #region Methods

        void SetValue(T value);

        #endregion Methods
    }