在测试遗留代码时添加Virtual关键字

本文关键字:添加 Virtual 关键字 代码 测试 | 更新日期: 2023-09-27 18:07:52

我正在向一些粗糙的遗留代码添加测试,以便有足够的信心认真重构它。其中一个问题是,编写代码的人显然没有尝试使代码可测试(考虑到他们从未编写过单个单元测试!)

一个常见的问题是目前没有接口,只有一个11层深度的继承链。我使用Rhino Mocks将被测试的类与其依赖关系隔离开来,但是由于我模拟的是一个类,而不是一个接口,因此如果它具有virtual关键字,我只能存根只读属性。

我目前的想法是,我将只是添加virtual关键字的属性。没有计划在现有的依赖链中添加任何进一步的对象,它将允许编写测试。

是否有任何反对添加virtual关键字的论据,或者这是一个可以接受的妥协,以便获得测试?

示例代码…

在测试类中:

var someClassStub = MockRepository.GenerateStub<SomeClass>();
someClassStub.Stub(s => s.SomeProperty).Return("Test");
在SomeClass:

public virtual string SomeProperty {
    get {
        return someDependency.SomeMethod();
    }
}

在测试遗留代码时添加Virtual关键字

反对添加virtual的主要理由是它歪曲了您的意图。virtual关键字向派生类发出信号,表示您期望该属性可以被覆盖。

我不会使用virtual,而是像下面这样模拟依赖:

var mockedDependency = MockRepository.GenerateMock<IDependency>();
mockedDependency.Expect(x => x.SomeMethod())
                .Returns("whatever your test dictates");
var target = new SomeClass(mockedDependency);
mockedDependency.VerifyAllExpectations();

然后将其注入到新创建的重载构造函数中,如下所示:

public SomeClass(IDependency dependency) : base()
{
    this.someDependency = dependency;
}

不需要到处添加virtual,这里有一些更安全的方法可以使您的代码最初是可测试的。就我个人而言,我强烈建议使用Visual Studio提供的"提取接口"工具,并在可能安全的情况下用接口替换具体的类引用。然后,模拟接口而不是具体类。

如果你使用的是Visual Studio(或其他IDE)不支持Extract Interface的版本,你所要做的就是追踪类的所有公共成员,并将它们添加到接口中,然后让你的具体类实现它。

你的首要任务应该是得到最初的一组测试。通过这种方式,您可以在合理确定代码没有被破坏的情况下进行更危险的更改。

对于任何致力于使旧的遗留代码单元可测试的人,我强烈建议阅读《有效地使用遗留代码》这本书。这是非常值得的。以至于我的经理最后给我的办公室买了一本供参考。