C# 单元测试继承

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/541083/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 07:24:16  来源:igfitidea点击:

Unit testing inheritance

c#unit-testingtdd

提问by trendl

I have a question concerning unit testing. Let's say that I have several classes that inherit behaviour from a parent class. I don't want to test all the child classes for this behaviour. Instead I would test the parent class. However, I should also provide a test proving that the behaviour is available in the child classes. Do you think something like Assert.IsTrue(new ChildClass() is ParentClass) makes sense?

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

采纳答案by joel.neely

If you're using a state-of-the-art unit-testing framework, I don't understand the statement

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

I don't want to test all the child classes for this behaviour.

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

Your unit tests (written against an instance of the parent class) should work unchanged if you hand them an instance of a child class, providedthat your child class hasn't overridden some aspect of the parent's behavior in a way that breaks the contract on the inherited methods. And that's exactly what you need to be testing, isn't it?

如果您将子类的实例交给他们,则您的单元测试(针对父类的实例编写)应该保持不变,前提是您的子类没有以违反以下约定的方式覆盖父类行为的某些方面继承的方法。这正是您需要测试的内容,不是吗?

If you're concerned about the time it takes to run the tests, I'd double-check to make sure that your tests are partitioned such that you can selectively run tests based on what you're actively working on (but still run the full portfolio periodically to catch unintended dependencies.)

如果您担心运行测试所需的时间,我会仔细检查以确保您的测试已分区,以便您可以根据您正在积极开展的工作有选择地运行测试(但仍然运行定期完整的投资组合以捕获意外的依赖项。)

回答by tvanfosson

I think that writing a test that inheritance works is a waste of time. The compiler will check that the base class methods are available if you try to use them, assuming you don't catch with intellisense. I would probably test the behavior in one child class and then only in each child class that modifies the behavior (or some state the behavior depends on).

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

回答by Spence

You wouldn't want to test the type of the object, unlessit's coming out of an untyped factory method. Otherwise you're writing a unit test against the C# compiler which is not what you want to do.

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

回答by Matthew

The C# compiler takes care of that kind of check for you.

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

If you like you can write something like:

如果你喜欢,你可以写一些类似的东西:

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

回答by Michael Meadows

There are two approaches you can use to test the behaviorof the base class:

您可以使用两种方法来测试基类的行为

  1. Create a stub implementation of the base class, and unit test the stub. Only test the public methods. It's pointless to test your private and protected methods, since those will be consumed by public methods that you should test in your subclasses. This approach will not enforce that your implementations of the base class hasn't shadowed behavior incorrectly.
  2. Create test superclass for your unit tests that exercises the base class methods. Whenever you're testing a subclass of your base class, have your test class inherit from your test superclass. This approach ensures that you haven't changed the behavior of the base class inadvertently, but limits the flexability of your test.
  1. 创建基类的存根实现,并对存根进行单元测试。只测试公共方法。测试私有方法和受保护方法是没有意义的,因为它们将被您应该在子类中测试的公共方法使用。这种方法不会强制您的基类实现没有错误地隐藏行为。
  2. 为执行基类方法的单元测试创​​建测试超类。每当您测试基类的子类时,让您的测试类从您的测试超类继承。这种方法可确保您不会无意中更改基类的行为,但会限制测试的灵活性。

Don't bother to verify that inheritance actually works (the whole Assert.IsTrue(new ChildClass() is ParentClass)thing). You should only test behavior. This is a structural feature of the .Net framework (inheritance), and you should trust that it works, otherwise you'll find yourself in a downward spiral of checking framework features.

不要费心去验证继承是否真的有效(整个Assert.IsTrue(new ChildClass() is ParentClass)事情)。您应该只测试行为。这是 .Net 框架(继承)的结构特征,您应该相信它有效,否则您会发现自己处于检查框架特征的螺旋式下降中。

回答by Bwing

make your tests inherit from a base class test, something [very]roughly like this.

让您的测试从基类测试继承,[非常] 大致像这样。

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();
    }
}

most of the popular test frameworks will run the test method in the base test when running the subclass tests.

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

or maybe have a look at something like https://github.com/gregoryyoung/grensesnitt

或者看看类似https://github.com/gregoryyoung/grensnitt 的东西

回答by MikeT

My opinion is that your Test Structure should reflect your object structure so if you have Class Car that Inherits from Class Vehicle

我的观点是你的测试结构应该反映你的对象结构,所以如果你有继承自 Class Vehicle 的 Class Car

then you should have Class TestCar that inherits from Class TestVehicle

那么你应该有从 Class TestVehicle 继承的 Class TestCar

By doing this Test car automatically inherits the correct tests for all Vehicle tests this means that if the function is overridden in Car it will most likely break the test highlighting that a Overriden Test is required in Car to support the new behaviour, if the test isn't broken then the override was probably superfluous in the first place

通过这样做,测试汽车会自动继承所有车辆测试的正确测试,这意味着如果该功能在汽车中被覆盖,它很可能会破坏测试,突出显示汽车中需要覆盖测试来支持新行为,如果测试是没有坏,那么覆盖首先可能是多余的

eg

例如

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);
    }
}

NOTE:Inheritance should only be used when testing inherited objects, not just because you want to do the same test on 10 unrelated objects. if you want to do that I'd suggest a static helper class

注意:继承只应在测试继承对象时使用,而不仅仅是因为您想对 10 个不相关的对象进行相同的测试。如果您想这样做,我建议您使用静态助手类