将 Autofac 和 Moqs 与委托工厂一起使用

Using Autofac and Moqs with Delegate Factories

我正在尝试对使用工厂注入的 class 进行单元测试。我有一个 class 实例化同一对象的两个副本(具有不同的配置)来控制硬件。我正在尝试在模拟硬件调用时测试 classes 的行为。

我已经将一组工厂委托注入到构造函数中,以便 class 可以根据需要实例化硬件 classes。但是,我就是不知道如何在 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 以便它 returns 我的设置模拟对象,以便我可以探测管理器的行为。

我的测试系统创建了 HWManager 的具体实例。我意识到在一个完美的场景中我会分别测试 HwManager 和 SUT,但我专门测试这两个组件的集成。

我想配置 autofac 来控制委托工厂。如果这不可能,那么我可以手动设置 SUT,但是我没有从 autofac 助手那里得到任何值。

我通常只创建一个 Func returns 我的模拟实例,例如

var controller = mock.Provide<IHWController>();
var manager = new HwManager(something, (uri) => controller);

如果工厂表达 "given a Uri I will provide a controller",我上面示例中的 lamda 满足该声明。

顺便说一句,您应该使用接口而不是具体的方式来表达您的工厂 类。当工厂生产具体的 类 而不是接口(它总是可以被模拟)时,它使得单元测试变得更加困难,例如

// IHwController is the product of the factory instead of HwController
public HwManager(HwType type, Func<Uri, IHwController> ControlFactory)

如果以后有人遇到这个问题,关键是创建一个与构造函数相匹配的函数,自定义以在每次调用时提供适当的模拟(例如通过内部计数器)。

然后您可以使用 mock.Provide() 语法,提供一个将构造函数与您在上面创建的函数相匹配的函数。这将被正确调用,允许您适当地控制模拟。