单元测试不同的类层次结构

时间:2013-02-23 14:46:30

标签: oop unit-testing testing tdd

制作考虑不同类层次结构的单元测试的最佳方法是什么,例如:

我有一个基类Car和另一个基类Animal

Car拥有派生类VolksWagenFord。 Animal拥有派生类DogCat

您如何开发测试,在运行时决定您将使用哪种对象。 考虑到这些测试将应用于数百万个对象,在不使用代码复制的情况下实现这些测试的最佳方法是什么 来自不同的等级?

这是向我的一位朋友询问的面试问题。

3 个答案:

答案 0 :(得分:1)

我看到的问题:避免重复常用测试来验证公共基类型的n个派生。

  • 创建一个抽象的测试夹具。在这里,您可以根据基本类型编写测试。在抽象基类(搜索术语'抽象测试夹具')中使用抽象方法GetTestSubject()。此类型的派生会覆盖返回要测试的类型的实例的方法。因此,您需要使用单个重写方法编写N个子类型,但您的测试将被编写一次。
  • 某些单元测试框架(如NUnit)支持“参数化测试”(搜索术语) - 您必须实现一个方法/属性,该方法/属性将返回需要运行测试的所有对象。然后,它将在运行时针对每个此类对象运行一个/所有测试。这样您就不需要编写N个派生 - 只需要一种方法。

答案 1 :(得分:0)

这是我之前使用的一种方法(嗯,这是一种变体)。

假设您在Car上有某种常用方法(go),您想要测试所有类,以及某些在子类中具有不同行为的特定方法(breakDown),因此:

public class Car {
    protected String engineNoise = null;

    public void go() {
        engineNoise = "vroom";
    }

    public void breakDown() {
        engineNoise = null;
    }

    public String getEngineNoise() {
        return engineNoise;
    }
}

public class Volkswagen extends Car {
    public void breakDown() {
        throw new UnsupportedOperationException();
    }
}

然后您可以按如下方式定义测试:

public abstract class CarTest<T extends Car> {
    T car;

    @Before
    public void setUp() {
        car = createCar();
    }

    @Test
    public void testVroom() {
        car.go();
        assertThat( car.getEngineNoise(), is( "vroom" ) );
    }

    @Test
    public void testBreakDown() {
        car.breakDown();
        assertThat( car.getEngineNoise(), is( null ) );
    }

    protected abstract T createCar();
}

现在,由于Volkswagen需要在testBreakDown方法中执行不同的操作 - 并且可能还有其他需要测试的方法 - 因此您可以使用以下VolkswagenTest。< / p>

public class VolkswagenTest extends CarTest<Volkswagen> {
    @Test(expected = UnsupportedOperationException.class)
    public void testBreakdown() {
        car.breakDown();
    }

    protected Volkswagen createCar() {
        return new Volkswagen();
    }
}

希望有所帮助!

答案 2 :(得分:0)

实际单元测试是指方法测试,当您想要编写单元测试时,您必须考虑要编写和测试的方法的功能,然后创建用于测试的类和方法。通过在设计和编写代码时考虑这种方法,可能会创建类的层次结构,或者只创建单个类或任何类型的其他设计。

但是当您必须像上面提到的那样使用现有设计时,最佳做法是使用InterfacesBase Classes作为依赖对象,因为通过这种方式,您可以模拟或存根这些类容易。