Использование 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)
Другие вопросы по тегам