Skip to main content
4 of 4
added 6229 characters in body

Mocking objects using abstract factory

For some time I am trying to make a mocking library for C# that mocks objects with just 1 line of code. I am using abstract factory pattern to know what is the object's type so that I can work with concrete factories.

I have the following Abstract factory class which I am not very happy with.

public class MockContext<T>
{
   public T CreateMockObject()
   {
      IFactory<T> factory = null;

     if (typeof(T).IsPrimitive || typeof(T) == typeof(string) || typeof(T) == typeof(decimal))
     {
        factory = new PrimitiveFactory<T>();
     }
     else if (typeof(T).IsArray)
     {
        factory = new ArrayFactory<T>();
     }
     else if (typeof(IEnumerable).IsAssignableFrom(typeof(T)))
     {
        factory = new CollectionFactory<T>();
     }
     else if (typeof(T).IsClass && typeof(T) != typeof(string))
     {
        factory = new ClassFactory<T>();
     }

      return factory.Create();
  }
 }
}

Which gets called by the following class

   public class Mocker
   {
      public T MockObject<T>()
      {
         MockContext<T> context = new MockContext<T>();
         T mockObject = context.CreateMockObject();

         return mockObject;
      }
   }

This abstract factory instantiates other factories depending on of the object.

Here is my class factory:

   public class ClassFactory<T> : IFactory<T>
   {
      public T Create()
      {
         T mockObject = (T)Activator.CreateInstance(typeof(T));
         IEnumerable<PropertyInfo> properties = typeof(T).GetProperties().Where(p => p.CanWrite);

         GenericMethodInvokerUtil method = new GenericMethodInvokerUtil();

         foreach (PropertyInfo property in properties)
         {
            if (property.PropertyType == typeof(T))
               throw new Exception("Circular properties are not supported!");

            method.InvokeMockObject<T>(property.PropertyType, property, mockObject);
         }

         return mockObject;
      }
   }

Here is my Primitive factory:

   public class PrimitiveFactory<T> : IFactory<T>
   {
      private readonly Dictionary<Type, IPrimitiveFactory<T>> _primitiveFactories = new Dictionary<Type, IPrimitiveFactory<T>>()
      {
         { typeof(string), new StringFactory() as IPrimitiveFactory<T> },
         { typeof(bool), new BooleanFactory() as IPrimitiveFactory<T> },
         { typeof(byte), new ByteFactory() as IPrimitiveFactory<T> },
         { typeof(sbyte), new SbyteFactory() as IPrimitiveFactory<T> },
         { typeof(char), new CharFactory() as IPrimitiveFactory<T> },
         { typeof(decimal), new DecimalFactory() as IPrimitiveFactory<T> },
         { typeof(double), new DoubleFactory() as IPrimitiveFactory<T> },
         { typeof(float), new FloatFactory() as IPrimitiveFactory<T> },
         { typeof(int), new IntFactory() as IPrimitiveFactory<T> },
         { typeof(uint), new UintFactory() as IPrimitiveFactory<T> },
         { typeof(long), new LongFactory() as IPrimitiveFactory<T> },
         { typeof(ulong), new UlongFactory() as IPrimitiveFactory<T> },
         { typeof(short), new ShortFactory() as IPrimitiveFactory<T> },
         { typeof(ushort), new UshortFactory() as IPrimitiveFactory<T> },
         { typeof(object), new ObjectFactory() as IPrimitiveFactory<T> },
      };

      public T Create()
      {
         if (_primitiveFactories.ContainsKey(typeof(T)))
         {
            IPrimitiveFactory<T> primitiveFactory = _primitiveFactories[typeof(T)];
            return primitiveFactory.Create();
         }

         throw new KeyNotFoundException($"The key of type: {typeof(T)} is not found.");
      }
   }

All primitive types has their own factories which is determined by the type of the object.

Array factory:

public class ArrayFactory<T> : IFactory<T>
   {
      public T Create()
      {
         var genericMethodInvoker = new GenericMethodInvokerUtil();
         Array array = Activator.CreateInstance(typeof(T), new object[] { RandomUtil.Instance.Next(1, 100) }) as Array;
         for (int i = 0; i < array.Length; i++)
         {
            Type arrayElementType = typeof(T).GetElementType();
            array.SetValue(genericMethodInvoker.InvokeMockObject<T>(arrayElementType), i);
         }

         return (T)Convert.ChangeType(array, typeof(T));
      }
   }

Collection factory

   public class CollectionFactory<T> : IFactory<T>
   {
      public T Create()
      {
         ICollectionFactory<T> factory = null;

         if (typeof(IDictionary).IsAssignableFrom(typeof(T)))
         {
            factory = new DictionaryFactory<T>() as ICollectionFactory<T>;
         }
         else if (typeof(IList).IsAssignableFrom(typeof(T)))
         {
            factory = new ListFactory<T>() as ICollectionFactory<T>;
         }

         return factory.Create();
      }
   }

Collections are on the other hand are separated in tow Dictionary and List

public class DictionaryFactory<T> : ICollectionFactory<T>
   {
      public T Create()
      {
         GenericMethodInvokerUtil methodInvoker = new GenericMethodInvokerUtil();
         IDictionary dictionary = (IDictionary)Activator.CreateInstance(typeof(T));
         int numberOfElements = RandomUtil.Instance.Next(1, 100);

         Type[] arguments = dictionary.GetType().GetGenericArguments();
         Type keyType = arguments[0];
         Type valueType = arguments[1];

         for (int i = 0; i < numberOfElements; i++)
         {
            object key = methodInvoker.InvokeMockObject<object>(keyType);
            object value = methodInvoker.InvokeMockObject<object>(valueType);

            if (!dictionary.Contains(key))
            {
               dictionary.Add(key, value);
            }
         }

         return (T)dictionary;
      }
   }

And List factory

public class ListFactory<T> : ICollectionFactory<T>
   {
      public T Create()
      {
         GenericMethodInvokerUtil methodInvoker = new GenericMethodInvokerUtil();
         IList list = (IList)Activator.CreateInstance(typeof(T));

         int numberOfElements = RandomUtil.Instance.Next(1, 100);
         Type valueType = list.GetType().GetGenericArguments()[0];

         for (int i = 0; i < numberOfElements; i++)
         {
            object value = methodInvoker.InvokeMockObject<object>(valueType);
            list.Add(value);
         }

         return (T)list;
      }
   }

I am using the above code as follows:

  static void Main(string[] args)
  {
     Mocker mocker = new Mocker();
     var mock = mocker.MockObject<Test>();
  }

With Test being some class with properties.

Mock object gets called recursively from the following utility class:

   public class GenericMethodInvokerUtil
   {
      public object InvokeMockObject<T>(Type type, PropertyInfo property, object currentObject)
      {
         object concreteResult = GetMockObjectResult(type);
         property.SetValue(currentObject, concreteResult);

         return currentObject;
      }

      public object InvokeMockObject<T>(Type type)
      {
         object concreteResult = GetMockObjectResult(type);
         return concreteResult;
      }

      private object GetMockObjectResult(Type type)
      {
         MethodInfo method = typeof(Mocker).GetMethod("MockObject", new Type[0] { });
         MethodInfo generic = method.MakeGenericMethod(type);

         object instance = Activator.CreateInstance(typeof(Mocker));
         object result = generic.Invoke(instance, null);
         object concreteResult = Convert.ChangeType(result, type);

         return concreteResult;
      }
   }

Can anyone suggest how to write this better?

Maybe there is a pattern that I am not familiar with. Any help would be appreciated.

You can find the complete source of the project in my github HERE.