【问题标题】:MSTest/Simple Injector: access service reference in created instance in order to mock one of its methodsMSTest/Simple Injector:在创建的实例中访问服务引用以模拟其方法之一
【发布时间】:2017-09-29 21:04:44
【问题描述】:

我有一个取决于服务的课程。我已经注册了它:

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

在为此类编写测试时,我想模拟 IChild 中的一种方法。所以我有 mockICild.Setup(...etc)。

但是你不能注册模拟类型,所以我必须在测试中手动实例化 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 - 感谢所有提供答案的人。

【问题讨论】:

标签: c# unit-testing mstest simple-injector


【解决方案1】:

在进行单元测试时,请避免使用 DI 容器来构造被测类。而是手动构建具有模拟依赖项的类。

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

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

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

  • 它可以防止每个单元测试都必须自己创建被测类。这会导致重复代码和噪音。
  • 它防止对被测类构造函数的更改导致测试类中的每个测试都发生更改。如果添加了依赖项,则现有测试都不会更改;只有工厂方法。
  • 单元测试只需定义它明确想要断言的依赖项。这简化了测试,因为它消除了不需要的依赖项的噪音。​​
  • 它允许测试定义自己的模拟依赖项,而不是将所有模拟放在私有字段中,由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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    • 1970-01-01
    相关资源
    最近更新 更多