【问题标题】:How test code with lots of dependencies如何测试具有大量依赖项的代码
【发布时间】:2011-10-31 03:46:08
【问题描述】:

我正在开发一个基本上没有单元测试覆盖率的大型代码库。我们即将开始转向一种更加测试驱动的方法,所以我想我会尝试为我添加的一个非常简单的函数编写一个单元测试,基本上是

class ClassUnderTest  {
    public void SetNoMatchingImage() {
        currentState.State = FSMState.NoMatchingImage;
        ... // Some more logic
        NotifyViews();
    }

    public ViewStatus GetStatus() {
        ...
        if (currentState.State == FSMState.NoMatchingImage)
           return ViewStatus.EmptyScreen;
        ...
    }

    ...
}

好的,所以测试一下,我只想这样做:

[Test]
public void TestSetNoMatchingImage() {
    ClassUnderTest view = new ClassUnderTest(...);
    view.SetNoMatchingImage();  
    Assert.AreEqual(ViewStatus.EmptyScreen, view.Status); 
}

但我的问题是 ClassUnderTest 构造函数将 3 个参数传递给不能为 null 的非接口,因此我无法轻松创建 ClassUnderTest。我可以尝试创建这些类的实例或存根它们,但它们的问题是相同的:每个构造函数都接受必须创建的参数。问题是一样的......等等。结果当然是非常大的开销,即使是非常简单的测试也需要大量代码。

有没有很好的办法来处理这样的用例,让测试用例更容易编写?

【问题讨论】:

  • 你不能为你的班级创建一个外观模型吗?

标签: c# unit-testing dependencies


【解决方案1】:

我赞成 Typemock 的建议,以及其他答案中建议的解决方案。除了已经说过的内容之外,Michael Feathers 还写了一本书来处理您遇到的模式,名为“有效地使用遗留代码”-

http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052/ref=sr_1_1?ie=UTF8&qid=1313835584&sr=8-1

这里有一个 PDF 摘录 - http://www.objectmentor.com/resources/articles/WorkingEffectivelyWithLegacyCode.pdf

【讨论】:

    【解决方案2】:

    如果在设计时没有考虑到依赖注入,并且您使用的模拟框架无法模拟具体类(例如 NMock),那么当您开始在没有测试的情况下重构项目时,您将遇到很多这样的情况。

    正如 Andriys 刚刚提到的,Typemock(以及 moq 也是)可以模拟具体类,只要它有虚拟成员。

    就个人而言,我会从这三个类中的每一个中提取一个接口,并将这些接口作为重构的一部分注入,以使该类易于测试。我不记得 VS 是否有重构以在 2 次单击中提取界面,这不会花费太长时间。

    【讨论】:

      【解决方案3】:

      我建议查看 Typemock Isolator 框架。根据 Roy Osherove 的《单元测试艺术》一书,为遗留代码编写单元测试时最好的选择:

      ...它是唯一一个 [框架] 允许您在生产代码中创建依赖项的存根和模拟,而根本不需要重构它,从而节省了测试组件的宝贵时间。

      干杯!

      【讨论】:

        猜你喜欢
        • 2014-07-01
        • 2017-03-10
        • 2016-02-04
        • 1970-01-01
        • 1970-01-01
        • 2012-01-01
        • 2014-07-25
        • 2016-09-30
        • 2011-12-20
        相关资源
        最近更新 更多