模拟一个超类构造函数

时间:2012-05-02 20:41:25

标签: java junit guice mockito jmock

我想知道我是否可以模拟超类构造函数调用及其super()调用。

例如,我有以下类

class A
{
    A(..)
    {
        super(..)
    }
}   

class B extends A
{
    B(C c)
    {
        super(c)
    }
}

所以,我计划对B类中的一些方法进行单元测试,但是在创建实例时,它会调用超类构造函数,这使得编写单元测试变得困难。那么,我如何模拟所有超类构造函数调用。此外,我想在A类中模拟几个方法,以便它确实返回我需要的几个值。

谢谢!

3 个答案:

答案 0 :(得分:1)

您可以使用PowerMock库。当你需要完成像你这样的事情时,它真的是一种救星。 https://github.com/powermock/powermock/wiki/Suppress-Unwanted-Behavior

答案 1 :(得分:1)

模拟构造函数是一个非常糟糕的主意。这样做是为了规避在生产中发生的行为。这就是为什么在构造函数中进行工作(例如启动线程和调用外部依赖项)是design flaw

您能否诚实地说,构造函数中执行的工作对您尝试测试的行为没有影响?如果答案是否定的,那么您将面临编写将在测试环境中通过但在生产中失败的测试的风险。如果答案是肯定的,那么在构造函数之外移动“工作”就是一个简单的例子。另一种方法是将您尝试测试的行为移动到另一个类(可能是它自己的)。

如果您正在使用像Guice这样的DI框架(我假设因为您以这种方式标记了它),情况更是如此。

答案 2 :(得分:0)

对你的问题的简短回答是"不完全是。"你不能嘲笑'一个构造函数,更不用说超级了。使用我熟悉的模拟框架,模拟super.anyMethod也很困难或不可能。 Powermock 确实允许你压制超级构造函数和有问题的方法,这与模拟它们并不完全相同,但可以提供帮助。

当B扩展A时,它当然与A完全耦合。这不是本身的问题,但它可以是,它看起来就像在这里。不要让B扩展A,而是尝试让B包含A(如果需要,可能实现相同的接口)。然后,您可以注入模拟A并委派您想要的所有调用。单元测试会更容易,不是吗?

测试驱动开发的好处之一是您在测试期间在设计中发现了这些内容。