如何测试具有大量依赖性的代码

时间:2011-08-20 09:57:52

标签: c# unit-testing dependencies

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

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。我可以尝试创建这些类的实例或者将它们存根,但问题是相同的:每个构造函数都接受必须创建的参数。问题也是如此......等等。结果当然是一个非常大的开销,即使是非常简单的测试也需要很多代码。

是否有一种处理此类案例的好方法可以使测试用例更容易编写?

3 个答案:

答案 0 :(得分:2)

当你开始重构一个没有测试的项目时,你会遇到很多这样的情况,如果它没有考虑到Dependency Injection的设计,你使用的模拟框架就不能模拟具体的类(比如NMock)。

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

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

答案 1 :(得分:1)

我建议看一下Typemock Isolator框架。根据Roy Osherove的Art of Unit Testing一书,在为遗留代码编写单元测试时,这是你最好的选择:

  

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

干杯!

答案 2 :(得分:0)

我推荐了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