Как мне смоделировать фабричный шаблон для поддержки модульного тестирования? - PullRequest
0 голосов
/ 03 октября 2019

У меня есть две операции, которые нужно сделать. Один для Air transport и один для Road transport. оба процесса некоторые message.

Вот это Interface

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

Вот моя реализация Road transport

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

Вот моя реализацияAir transport

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

Теперь я покажу фабричный класс, который будет возвращать различные объекты на основе 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;
        }
   }

Вот мой класс, который должен быть проверен

  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");
            }
        }
  }

Как выполнить модульное тестирование этого контроллера, поскольку для класса factor не определено interface? мне нужно mock заводской класс или это неправильный дизайн?

1 Ответ

1 голос
/ 03 октября 2019

Должен ли я издеваться над фабричным классом

НЕТ . Не высмеивайте проблемы реализации, насмехайтесь над абстракциями.

или это неправильный дизайн?

Это не гибкий дизайн, поскольку ваши классы тесно связаны с проблемами конкретизации / реализациикоторые плохо поддаются изолированным модульным тестам.

Как выполнить модульное тестирование этого контроллера, поскольку для класса факторов не определен интерфейс?

Затем определитеабстракция (контракт) для завода. (Может быть интерфейсом или абстрактным классом)

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

и иметь реализацию, унаследованную от абстракции

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

Теперь контроллер может быть реорганизован для явной зависимости от абстракции с помощью инъекций конструктора.

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

}

Теперь это позволяет заменять макет при тестировании контроллера в изоляции.

Предполагается, что MyConfigurations - это POCO, хранящий настройки / опции, которые не падают. при функциональных проблемах, требующих абстракции.

Последний шаг будет заключаться в обеспечении того, чтобы фактическая производная реализация фабрики вводилась в контроллер при производстве.

...