请问可以简单总结一下,使用PowerMock相较于仅使用Mockito,有哪些增加的功能?
目前我已经发现以下几点:
- 能够Mock静态、final和私有方法
- 移除静态初始化器
- 允许在无需依赖注入的情况下进行Mock - 对我来说这一点不是很清楚。能否详细说明一下?
除此之外,它还有其他的新增功能吗?能否简要总结一下?
同时,在使用PowerMock的过程中,是否需要做出任何牺牲?
请问可以简单总结一下,使用PowerMock相较于仅使用Mockito,有哪些增加的功能?
目前我已经发现以下几点:
除此之外,它还有其他的新增功能吗?能否简要总结一下?
同时,在使用PowerMock的过程中,是否需要做出任何牺牲?
我不知道其他好处,但我想解决你的两个子问题(这篇评论太长了):
允许在没有依赖注入的情况下进行mocking——这个对我来说不太清楚。你能详细说明一下吗?
我认为这源自动机维基页面,其中他们描述了一种重构代码的方法,以避免调用静态方法从而使它可测试。为了更具体地说明他们的意思,假设你有以下代码,并且想要测试该方法,模拟静态方法的行为,但不使用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,您可能会被诱惑只是模拟它并继续前进,这将减轻应该鼓励您重构相同代码时的痛苦。是的,有时候由于各种技术和非技术限制,这是不可能的,但最好是解决痛点而不是避免它们:)
final
、new
和static
意味着你需要牺牲某些有用的设计选择。 - Rogériofinal
、new
或static
,但是我认为如果我选择使用这些方法,其中的代码不应该需要模拟。如果它们非常复杂或布满副作用,那么我可能应该考虑将其封装到其他对象中,这样我就可以在测试时注入模拟对象或在实现更改时注入模拟对象。(更不用说像Guice这样的依赖注入框架 - "@Inject是新的新东西" :D)PowerMock 是 Mockito 的扩展,可以模拟静态方法、构造函数、final 类和方法、私有方法,移除静态初始化器等等。
Powermock mockito扩展的另一个功能是支持模拟和存根等于和哈希码。
与所有powermock功能一样,需谨慎使用,但为特定结果添加(基于值的)相等性可能会有所帮助。
org.mockito.plugins.MockMaker
。您需要做的是:
test/resource
文件夹中创建一个名为mockito-extensions
的文件夹。org.mockito.plugins.MockMaker
的文件。mock-maker-inline