2009-02-12 105 views
9

我有一个关于单元测试的问题。假设我有几个继承父类行为的类。我不想测试所有这些行为的子类。相反,我会测试父类。但是,我还应该提供一个测试,证明行为在子类中可用。你认为像Assert.IsTrue(新的ChildClass()是ParentClass)有意义吗?单元测试继承

回答

7

如果您使用的是国家的最先进的单元测试框架,我不明白的声明

我不想测试所有的子类的这种行为。

单元测试(笔试对父类的一个实例)应该可以正常工作,如果你把他们一个子类的实例,提供,你的子类没有覆盖的某些方面父母的行为以某种方式打破了继承方法的契约。这正是你需要测试的,不是吗?

如果您担心运行测试所需的时间,我会仔细检查以确保您的测试已分区,以便您可以根据自己正在进行的工作选择性地运行测试(但仍然会定期运行完整的产品组合以捕获意想不到的依赖关系。)

+1

阿门。这是实际测试“继承有效”(即符合Liskov替代原则)的一个非常好的理由,而不是仅仅验证子类是父类的子类型。 – Sol 2009-02-12 13:43:14

+0

这不是我关心运行测试所花费的时间。我只想写出尽可能少的测试,以便在将来进行rafactoring。 – trendl 2009-02-13 10:28:19

8

我认为编写一个继承工作的测试是浪费时间。如果您尝试使用它们,编译器将检查基类方法是否可用,假设您没有捕捉到intellisense。我可能会测试一个子类中的行为,然后只在每个修改行为的子类中(或行为依赖的某个状态)进行测试。

5

你不想测试对象的类型,除非它来自一个无类型的工厂方法。否则,你正在编写一个针对C#编译器的单元测试,这不是你想要做的。

+0

你可以说,有一个测试,继承链没有被打破是一个有效的测试。毕竟你可以让A类继承A类继承B类继承C类,并且在期货中的某个时刻开发者决定A直接指向C会更好,因为意识到A依赖于由B – MikeT 2015-06-09 11:27:25

1

C#编译器为您处理这种检查。

如果你喜欢你可以写这样的:

ParentClass childClass = new ChildClass() 
var testOutput = childClass.ParentMethod(); 
Assert.IsNotNull(testOutput); 
0

有,你可以用它来测试基类的行为两种方法:

  1. 创建的存根实现。基类和单元测试存根。只测试公共方法。测试你的私有和受保护的方法是毫无意义的,因为这些方法将被你应该在你的子类中测试的公共方法所使用。这种方法不会强制您的基类的实现没有错误地影响行为。
  2. 为您的单元测试创​​建测试超类,这些测试可以执行基类方法。每当你测试你的基类的一个子类时,让你的测试类继承自你的测试超类。这种方法可以确保您不会无意中更改基类的行为,但会限制测试的灵活性。

不要打扰来验证继承是否真正起作用(整个Assert.IsTrue(new ChildClass() is ParentClass)的事情)。你应该只测试行为。这是.Net框架(继承)的一个结构特征,你应该相信它是有效的,否则你会发现自己在检查框架功能方面处于下降的螺旋状态。

+0

执行的数据转换单元测试的定义是你测试最小的可能的组件,所以单一的方法和属性,这意味着你应该总是测试你的子呼叫 – MikeT 2015-06-09 11:18:23

6

使您的测试从基类测试继承,这非常类似于此。

public class MyBaseClass 
{ 
    public virtual void DoStuff() { } 
    public virtual void DoOtherStuff() { } 
} 

public class MySubClass : MyBaseClass 
{ 
    public override void DoOtherStuff() 
    { 
     // different to to base 
    } 
} 

public abstract class TestOfBaseClass 
{ 
    protected abstract MyBaseClass classUnderTest { get; } 

    [TestMethod] 
    public void TestDoStuff() 
    { 
     classUnderTest.DoStuff(); 
     Assert.StuffWasDone(); 
    } 
} 

[TestClass] 
public class WhenSubclassDoesStuff : TestOfBaseClass 
{ 
    protected override MyBaseClass classUnderTest 
    { 
     get { return new MySubClass(); } 
    } 

    [TestMethod] 
    public void ShoudDoOtherStuff() 
    { 
     classUnderTest.DoOtherStuff(); 
     Assert.OtherStuffDone(); 
    } 
} 

大多数流行的测试框架将在运行子类测试时在基本测试中运行测试方法。

或许看看像https://github.com/gregoryyoung/grensesnitt

0

我的看法是,你的测试结构应该反映你的对象结构 所以如果你有一流的汽车,从车辆类别

那么你应该有类继承TestCar继承自Class TestVehicle

通过这样做测试车自动继承了所有Vehicle测试的正确测试,这意味着如果在Car中覆盖函数,它很可能会突破测试突出显示Overriden Test在汽车,以支持新的行为要求,如果测试没有再分解倍率是摆在首位可能是多余的

class Vehicle 
{ 
    public virtual bool LicenceRequired 
    { 
     get{throw new NotImplmentedException() 
    } 
} 
class Bicycle:Vehicle 
{ 
    public override bool LicenceRequired 
    { 
     get{return false;} 
    } 
} 
class Car:Vehicle 
{ 
    public override bool LicenceRequired 
    { 
     get{return true;} 
    } 
} 
class TestVehicle 
{ 
    public virtual Void LicenceRequiredTest() 
    { 
     Try 
     { 
      LicenceRequired 
      Assert.Fail(); 
     } 
     Catch(){} 
    } 
} 
class TestBicycle:TestVehicle 
{ 
    public override void LicenceRequiredTest() 
    { 
     Assert.IsFalse(LicenceRequired); 
    } 
} 
class TestCar:TestVehicle 
{ 
    public override void LicenceRequiredTest() 
    { 
     Assert.IsTrue(LicenceRequired); 
    } 
} 

注:测试时继承继承,才应使用对象,不仅仅是因为你想对10个不相关的对象进行相同的测试。如果你想这样做,我会建议一个静态帮助类