Question

A month ago I finished reading the book "Art of Unit Testing" and today I finally had time to start using Rhino Mocks with unit testing a service that sends/receives messages to devices (UDP) and saves/loads data from the database.
Off course I want to isolate the database and the UDP communication.

For example for database access, we have some classes with static methods, let's call them:

  • AreaADBAccess
  • AreaBDBAccess
  • AreaCDBAccess

These classes had static methods that executed the database access.
To be able to stub them I made their methods public virtual.

Then I started refactoring the code to be able to replace the instance of these classes on the code.
After trying different things, I ended up with a factory class that seems to make things so easy.

public class ObjectFactory
{
    private static Dictionary<Type, object> Instances = new Dictionary<Type, object>();

    public static T GetInstance<T>() where T : new()
    {
        if(Instances.ContainsKey(typeof(T)))
            return (T)Instances[typeof(T)];

        return new T();
    }

    public static void SetInstance<T>(object obj)
    {
        Instances[typeof(T)] = obj;
    }
}

Then on the code, I can use

private AreaADBAccess DBAccess = ObjectFactory.GetInstance<AreaADBAccess>();

And on the test method I do something like

AreaADBAccess dbAccess = mocks.Stub<AreaADBAccess>();
using (mocks.Record())
{
...
}
ObjectFactory.SetInstance<AreaADBAccess>(dbAccess);
//Invoke the test method
...

This is a first solution and I realize that it can be done in a better way.
Can you now comment it and point me to the best practices?
Can you also explain to me why I would want to have an interface instead of defining the methods as virtual? It seems useless to repeat the method headers in 2 places.
Thanks!

Was it helpful?

Solution

Probably you could make use of IoC containers like, Windsor, StructureMap or Ninject, which would make your life much easier, and in fact they also work as "factory" you have created manually, but are much more powerful.

Also there are automocking containers which will automatically create mock dependencies for your classes so you can save additional lines of code, and make your test less fragile.

As for question regarding the need for interface instead of classes, its basically the Dependency Inversion Principle, which states that higher level modules (classes) should not depend on lower level modules (classes), both of them should depend on abstractions. Interfaces are those abstractions. I suggest you would take a look at S.O.L.I.D principles which will make your life much more easier, at least they did to me..

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top