kudlatiger
kudlatiger

Reputation: 3288

How do I mock factory pattern to support unit testing?

I have two operations to be done. One is for Air transport and one for Road transport. both processes some message.

Here is the Interface

   public interface IProcess
   {
        void Process(string message);
   }

Here is my implementation of Road transport

     public class RoadTransport: IProcess 
     {
         public void Process(string msg)
         {
             // do some road related operation
          }
     }

Here is my implementation of Air transport

     public class AirTransport: IProcess 
     {
         public void Process(string msg)
         {
             // do some air related operation
         }
     }

Now, I will show the factory class, which will return different objects based on ID

   public class MyFactory
   {
        private readonly AirTransport airtransport = null;
        private readonly RoadTransport roadtransport = null;

        public MyFactory(AirTransport, RoadTransport)// dependency injected
        {
             airtransport =  AirTransport;
             roadtransport = RoadTransport;
        }
        IProcess process = null;
        public IProcess GetInstance(int id)
        {
              swicth(id)
              {
                    case "1":
                    process = airtransport;
                    break;

                    case "2":
                    process = roadtransport;
                    break; 
              }
             return process;
        }
   }

Here is my class which supposed to be tested

  public class HomeController:Controller
  {
        private readonly MyFactory _myfactory;
        private readonly MyConfigurations _myConfigurations;

        public HomeController(MyFactory factory, MyConfigurations configurations)
        {
             _myfactory = factory;
        }

        public IActionResult Index()
        {
             return View();
        }

        Public ActionResult Process(string message, string id)
        {
            var configurations =  _myConfigurations;
            if(configurations!=null)
            {
               IProcess processor=  _myfactory.GetInstance(id);
               processor.Process(message);
               return View("Index");
            }
        }
  }

How do I unit test this controller, because there is no interface defined for factor class? do I have to mock the factory class or is it wrong design?

Upvotes: 0

Views: 3946

Answers (1)

Nkosi
Nkosi

Reputation: 247591

do I have to mock the factory class

NO. Do not mock implementation concerns, mock abstractions.

or is it wrong design?

It is not a flexible design as your classes are tightly coupled to concretions/implementation concerns that do not lend itself well to isolated unit tests.

How do I unit test this controller, because there is no interface defined for factor class?

Then define an abstraction (contract) for the factory. (Could be an interface or abstract class)

public interface IProcessFactory {
    IProcess GetInstance(int id);
}

and have the implementation derive from the abstraction

public class MyFactory : IProcessFactory {
    //...
}

The controller can now be refactored to explicitly depend on the abstraction via constructor injections.

public class HomeController : Controller {
    private readonly IProcessFactory factory;
    private readonly MyConfigurations configurations;

    public HomeController(IProcessFactory factory, MyConfigurations configurations) {
        this.factory = factory;
        this.configurations = configurations;
    }

    //...omitted for brevity

}

This now allows for a mock to be substituted when testing the controller in isolation.

The assumption is that MyConfigurations is a POCO storing settings/options that does not fall under functional concerns that require abstraction.

The final step would be to ensure that the actual derived factory implementation is injected into the controller in production.

Upvotes: 1

Related Questions