3

我不得不进行修复,第二次删除了代码行。所以我决定为此编写一个单元测试。

其构造函数中的 Class 设置了我要测试的属性。该属性恰好受到保护,因此我无法在单元测试中访问它。

 [Test]
 public void Constructor_WhenCalled_ThenSomePropertyIsPopulated()
 {
     var vm= new SomeViewModel();
     //line below doesn't compile as SomeProperty is protected
     Assert.IsNotNull(vm.SomeProperty);

因此,我决定在我的单元测试文件中扩展该类(它没有被密封)并将受保护的属性公开为公共 getter:

public class SomeViewModelExtended : SomeViewModel
{
    public SomeViewModelExtended() : base() { }

    public new object SomeProperty
    {
        get { return base.SomeProperty; }
    }
}

 //now I can test
 [Test]
 public void Constructor_WhenCalled_ThenSomePropertyIsPopulated()
 {
     var vm= new SomeViewModelExtended();
     Assert.IsNotNull(vm.SomeProperty);

现在我的团队有一个争论,我应该只测试公共接口以及其他东西,这是一个快速而肮脏的黑客攻击。

但是,单元测试的目的之一不是保护代码库免受不必要的更改吗?如果这是完全错误的,还应该做什么?

4

3 回答 3

3

受保护的变量接口的一部分。它是任何子类都可以使用的接口的一部分。这个问题对受保护的变量有很好的总结。 保护成员变量是一种好习惯吗?

如果您允许派生类访问其基类的数据,那么派生类需要注意不要使基类数据的不变量无效。这会将封装抛出窗外,这是错误的。(顺便说一句,getter 和 setter 也是如此。)

在回答您的问题时,如果子类不应访问该变量,那么它应该是private. 否则,您的单元测试是有效的,并且可以说它应该更早实施!

于 2013-06-07T19:30:19.573 回答
2

在阅读了Roy Osherove 的“单元测试艺术”之后,我对此的看法是,测试 + 可维护性是好的代码的主要用例。因此,我认为扩展类型以帮助测试的理由是非常有效的。

当然,如果您可以设计一个不需要它的类型,那很好,但是可维护性和可测试性是最重要的。

经常有人说泄漏抽象是一个糟糕的选择,但是我发现在大多数情况下这是因为没有考虑这两个主要用例。抽象应该对所有用户都有好处:功能、测试和维护。

于 2013-06-07T19:37:08.187 回答
1

您应该完全删除该字段,直到它实际需要通过外部测试。如果没有失败的外部行为,则不需要该字段。

由于该字段受到保护,我假设您创建它是为了从中派生一些东西。这个派生类是否需要受保护的字段才能通过它的任何测试?在这种情况下,你被覆盖了。

于 2013-06-07T19:30:13.050 回答