2012-02-03 54 views
3

我需要测试类SportCar,它扩展了汽车的代码。问题是,当我创建我的对象在测试JMockit:如何避免超的构造

SportCar car = new SportCar(); 

它还将从父类,例如Car()调用构造函数。这些构造函数做了很多事情,有很多环境依赖关系,并且需要很多我没有的配置文件,所以我想创建一个SportCar实例而不调用继承的构造函数。

我知道这个问题的唯一解决方案是创建一个样机的汽车中,我改写的构造函数($ INIT)和静态块($ clinit)。但现在我的问题是,如果我的层次结构中存在许多类(SportCar扩展Car,扩展了扩展B的C继承扩展C ...),我想避免所有构造函数,会发生什么?我应该为所有以前的课程创建Mocks吗?

class A extends B{ 
    public A(){ 
     // Plenty of things to avoid during tests 
    } 
} 

class Car extends A{ 
    public Car(){ 
     // Plenty of things to avoid during tests 
    } 
} 

class SportCar extends Car(){ 
} 
+3

如果你想有一个类跑车不具备汽车类的所有行李,然后没有从车,就这么简单继承。我觉得Car应该不是一个班级,而是一个界面。 – 2012-02-03 13:22:20

+2

同意@Hovercraft在这种情况下,继承是邪恶的。改用组合,并实现接口。如果你想“共享逻辑”为所有的汽车,把它在你注入SportCar(和取其他车需要它)的合作者对象 - 你可以有一个合作者对象的多种实现,这将实现相同的功能,你具有继承性,但以更简洁的方式 - 使测试更容易,这通常是良好设计的良好指标。 – Guillaume 2012-02-03 13:30:20

+0

这是旧代码,我不能改变,但无论如何,我不是说SportCar不需要Car的构造函数的继承代码。我只是表示我不想在测试期间调用此代码。我的意思是,SportCar需要继承Car的构造函数中的代码,但因为我想要一个单独的(单元)测试,所以我不想在测试过程中调用很多类。无论如何,我知道设计很糟糕:在构造函数中有这样的事情。有这么多的依赖关系... – 2012-02-03 13:41:46

回答

1

Car创建一个受保护的“什么都不做”的构造,并在SportsCar受保护的构造函数调用了它,并调用从您的测试类,可以看到构造顺便说一句 - 它拥有的权限做所以。

这可以被认为是“可测试性设计”图案的轻微拉伸。

+1

仅仅为了测试而在您的类中创建特殊的构造函数显然是错误的。更好的方法是从Car构造函数调用某个方法,为SportsCar类创建一个子类并覆盖包含所有加载步骤的方法。 – 2012-02-03 13:27:39

+0

谢谢你们两位。是的,我知道有更好的方法可以通过重构我们的代码来避免这种可怕的情况,但是这是一个庞大的项目,它带有旧代码,没有单元测试,所以我期望创建单元测试,但不要改变测试中的代码:(我的问题更多的是关于JMockit ...在设计方面,我还希望有一个不同的场景。 – 2012-02-03 13:35:27

1

可以抑制使用PowerMock

suppress(constructor(EvilParent.class)); 

然而父类的构造,如果你做了很多的单元测试,它可能是值得搞清楚如何捏造出来的enironment为好。或者说服其他开发者让你做一些重构,至少允许服务注入。

+0

+1“说服其他开发人员”。但我不相信,一个模拟框架提供 – Raedwald 2012-02-03 14:10:04

+0

我自己从来没有使用过这个功能,但是PowerMock使用自定义类加载器来操纵字节码本身,以允许静态方法被嘲笑 – 2012-02-03 14:12:55

+0

我发现PowerMock字节码操作有时会引起意想不到的复杂情况。绝对强大,但它必须是相当侵入性的。 – AHungerArtist 2012-02-03 15:36:23

4

如果您正在使用jmockit,你不必做任何事情,因为所有的超类的构造函数默认嘲笑。在你单元测试的方法,你可以做:

public void testMockedStuff(@Mocked final ClassToBeMocked instance) { 

有嘲笑你的东西。你甚至不必自己创建实例。 然后,您可以修改注释参数以排除您从模拟中获取的方法。