谁能总结一下,究竟是什么功能让您在 Mockito 之上添加了 PowerMock?
到目前为止,我已经找到了这些:
- 模拟静态、最终和私有方法
- 移除静态初始化器
- 允许在没有依赖注入的情况下进行模拟 - 我不清楚这一点。你能详细说明吗?
它是否添加了其他任何东西?你能概括几行吗?
使用 PowerMock 时我需要牺牲一些东西吗?
我不知道其他好处,但我想解决您的两个子问题(这对于评论来说太长了):
允许在没有依赖注入的情况下进行模拟 - 我不清楚这一点。你能详细说明吗?
我认为这来自Motivation wiki 页面,他们描述了一种重构代码的方法,以不调用静态方法来使其可测试。对于我认为他们正在做什么的一个具体示例,假设您有这段代码,并且您想测试模拟静态方法行为的方法,而不使用 powermock:
public class MyClass {
public void doGetString() {
...
OtherClass.getString(); //It's complex and scary and needs mocking!
...
}
}
一种解决方案是将静态调用拉到它自己的对象中,然后注入一个可以在测试时模拟的对象。例如,在不使用其他框架的情况下,这可能如下所示:
public class MyClass {
public static class StringGetter {
public getString() {
return OtherClass.getString();
}
}
private final StringGetter getter;
//Existing Constructor
public MyClass() {
this(new StringGetter());
}
//DI Constructor
MyClass(StringGetter getter) {
this.getter = getter;
}
public void doGetString() {
...
getter.getString();
...
}
}
我已经将我的方法的行为与静态调用的行为分开,并且可以使用 DI 构造函数在测试时轻松地注入模拟。当然,使用 powermock 我可以在适当的位置模拟静态方法,然后使用它运行。
使用 PowerMock 时我需要牺牲一些东西吗?
物理上没有,但我会在哲学上说是:)。以下是我的观点,我试图给出很好的理由,但当然它们是观点,所以对它们持保留态度:
PowerMock 发生的潜在可怕的事情是,为了完成模拟私有和静态方法的壮举,他们正在使用自定义类加载器(它不应该在生产运行时出现)并更改类的字节码. 可以说,在大多数情况下,这对绝大多数类都无关紧要,但如果你仔细想想,如果字节码发生了变化,并且某些副作用不再存在,那么你实际上是在根据你的现有的类。是的,这是一个非常学术的论点。
您可以通过良好的综合集成和不使用 PowerMock 的更高级别的测试来在一定程度上缓解第一个论点。通过这种方式,即使您的单元测试使用 PowerMock,您也可以对对象的行为更有信心。
我反对 PowerMock 的另一个论点是,它几乎太容易成为拐杖。我同意 PowerMock 可以帮助测试使用遗留代码和您无法控制的其他代码的代码。但是我认为,当您可以控制需要模拟的类时,您应该避免使用它。如果您编写一个带有私有方法或静态方法的类,您需要显式地模拟以测试其他方法,我的直觉会说这种方法可能做得太多,应该重构和分解。PowerMock 已经在项目中可用,您可能会想模拟它并继续前进,这将减轻应该鼓励您重构相同的痛苦。是的,有时由于各种技术和非技术限制,这是不可能的,但它'
PowerMock是 Mockito 的扩展,它允许模拟静态方法、构造函数、最终类和方法、私有方法、删除静态初始化程序等。
Powermock mockito 扩展的另一个特性是它支持对 equals 和 hashcode 进行模拟和存根。
与所有要谨慎使用的 powermock 功能一样,但为特定结果添加(基于值的)相等性可能会有所帮助。
PowerMock 的另一个特性是我们可以在方法中模拟新对象的构造。当我们无法更改要测试的方法的代码时,它会很有帮助。
对于模拟最终类,我们可以使用org.mockito.plugins.MockMaker
. 你需要做的是
test/resource
名为的文件夹mockito-extensions
。org.mockito.plugins.MockMaker
.mock-maker-inline
这将不需要您添加任何新库,从而节省一些运行时间。