我正在开发一个基本没有单元测试覆盖率的大型代码库。我们即将开始采用更加测试驱动的方法,所以我想我会尝试为我添加的一个非常简单的函数编写单元测试,基本上
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。我可以尝试创建这些类的实例或者将它们存根,但问题是相同的:每个构造函数都接受必须创建的参数。问题也是如此......等等。结果当然是一个非常大的开销,即使是非常简单的测试也需要很多代码。
是否有一种处理此类案例的好方法可以使测试用例更容易编写?
答案 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还写了一本书,讲述了你正在讨论的模式,称为“有效地使用遗留代码” -
这里有一个PDF摘录 - http://www.objectmentor.com/resources/articles/WorkingEffectivelyWithLegacyCode.pdf