MSTest/Simple 注入器:在创建的实例中访问服务引用以模拟其方法之一

MSTest/Simple Injector: access service reference in created instance in order to mock one of its methods

我有 class 取决于服务。我是这样注册的:

container.Register<IMain, Main>();
container.Register<IChild, Child>();

为此 class 编写测试时,我想模拟 IChild 中的一种方法。所以我有 mockIChild.Setup(...等).

但是你不能注册模拟类型,所以我将不得不在测试中手动实例化 Main,对吗?

或者在 Simple Injector 或 MSTest 的深处是否有一些神奇的东西可以做相当于:

[TestMethod]
public void foo()
{
    var mockChild = new Mock<IChild>();
    var main = container.GetInstance<IMain>(
       () => new Mock<IMain>(mockChild));
    mockChild.Setup(and so on...)'
}

?

干杯, .pd.

29-09-17 - 感谢所有提供答案的人。

在进行单元测试时,避免使用 DI 容器来构建被测 class。而是手动构建 class 及其模拟依赖项。

我一年来发现的一个好模式是在测试 class 中使用私有工厂方法,它允许构建被测 class:

private static Main CreateMain(
    IChild child = null, ILogger logger = null, IMessageSender sender = null)
{
    return new Main(
        child: child ?? new Mock<IChild>().Object,
        logger: logger ?? new Mock<ILogger>().Object,
        messageSender: sender ?? new Mock<IMessageSender>().Object);
}

此工厂方法允许有选择地提供依赖项。任何缺失的依赖项都将自动填充。这样做有以下优点:

  • 它避免了每个单元测试都必须自己创建 class 被测对象。这会导致重复代码和噪音。
  • 它防止更改 class 测试构造函数导致测试 class 中的每个测试发生变化。如果添加依赖项,则不会更改现有测试;只有工厂方法。
  • 单元测试只需定义它明确想要断言的依赖项。这简化了测试,因为它消除了不需要的依赖项的噪声。
  • 它允许测试定义自己的模拟依赖项,而不是将所有模拟放在私有字段中,由 Setup 方法实例化。 Setup 方法导致测试逻辑被拆分到多个地方,并导致测试的可读性降低,因为很难看出正在使用哪些依赖项。

工厂方法的用法如下:

public void Test()
{
    // Arrange
    var child = new Mock<IChild>();

    var main = CreateMain(child: child.Object);

    // Act
    main.DoSomething();

    // Assert
    Assert.IsTrue(child.ExpectSomethingOnChild);
}