Использование Autofac и Moqs с фабриками делегатов
Я пытаюсь провести модульное тестирование класса, в котором используется заводская инъекция. У меня есть класс, который создает две копии одного и того же объекта (с другой конфигурацией) для управления оборудованием. Я пытаюсь проверить поведение классов при моделировании аппаратных вызовов.
Я ввел набор фабричных делегатов в конструкторы, чтобы класс мог создавать экземпляры аппаратных классов по мере необходимости. Однако я просто не могу понять, как управлять или создавать фабричные методы в пакете Autofac.Extras.Moq. Кажется, что эта функциональность не поддерживается в пакете.
Я ищу эквивалентный вызов:
mock.Provide<IHWController>(//created by factory delegate)
Я хочу создать конкретный фиктивный объект с поведением на основе параметров, используемых для создания экземпляра HWcontroller. Возможно ли то, что я пытаюсь сделать?
class SystemUnderTest
{
SystemUnderTest(Ia a, Ib b, Ic c,
/** 15 other things **/
Func<Func<Uri, IHwController>, HwType, IHwManager> HwManagerFactory,
Func<Uri, IHwController> HwControllerFactory)
{
}
}
class HwManager()
{
public Func<HwType, Func<Uri, HwController>, HwManager> Factory;
public HwManager(HwType type, Func<Uri, HwController> ControlFactory)
{
//Constructor
}
}
Код, который я тестирую, создает Менеджеры контроллеров. Контроллер - это аппаратный уровень, но я тестирую сложное (связанное) поведение внутри менеджера. Поэтому я пытаюсь понять, как издеваться над Func<Uri, HwController> ControlFactory
чтобы он возвращал мои установочные макеты объектов, чтобы я мог проверить поведение менеджера.
Моя тестируемая система создает конкретный экземпляр HWManager. Я понимаю, что в идеальном сценарии я бы тестировал HwManager и SUT по отдельности, но я специально тестирую интеграцию двух компонентов.
Я хотел бы настроить автозапуск для управления фабрикой делегатов. Если это невозможно, тогда я могу вручную настроить SUT, но тогда я не получаю никакого значения от помощника по автозапуску.
2 ответа
Если кто-то зацикливается на этом в будущем, ключом является создание функции, которая соответствует функции конструктора, настроенной для предоставления соответствующих макетов при каждом вызове (например, с помощью внутреннего счетчика).
Затем вы можете использовать синтаксис mock.Provide(), предоставляя функцию, которая соответствует функции конструктора вышеупомянутой функции. Затем он будет вызван правильно, позволяя вам правильно контролировать макеты.
Я обычно просто создаю Func, который возвращает мой смоделированный экземпляр, например
var controller = mock.Provide<IHWController>();
var manager = new HwManager(something, (uri) => controller);
Если фабрика выражает "учитывая Uri, я предоставлю контроллер", то лямда в моем примере выше удовлетворяет этому утверждению.
Кроме того, вы должны выражать свои фабрики, используя интерфейсы, а не конкретные классы. Это значительно усложняет модульное тестирование, когда фабрики производят конкретные классы вместо интерфейсов (которые всегда можно смоделировать), например
// IHwController is the product of the factory instead of HwController
public HwManager(HwType type, Func<Uri, IHwController> ControlFactory)