在通常使用 @Mock
和 @InjectMocks
注释的模拟中,被测类应该使用 @RunWith(MockitoJUnitRunner.class)
运行。
@RunWith(MockitoJUnitRunner.class)
public class ReportServiceImplTestMockito {
@Mock
private TaskService mockTaskService;
@InjectMocks
private ReportServiceImpl service;
// Some tests
}
但在某些示例中,我看到 @RunWith(PowerMockRunner.class)
被使用:
@RunWith(PowerMockRunner.class)
public class Tests {
@Mock
private ISomething mockedSomething;
@Test
public void test1() {
// Is the value of mockedSomething here
}
@Test
public void test2() {
// Is a new value of mockedSomething here
}
}
有人可以指出有什么区别以及我什么时候想使用一个而不是另一个吗?
原文由 Johan 发布,翻译遵循 CC BY-SA 4.0 许可协议
乍一看,答案很简单:好吧,有几种模拟框架,而且有不同的使用方法。
第一个示例告诉 JUnit 使用 Mockito 模拟框架提供的“单元测试运行器”。第二个示例使用 PowerMock 框架中的单元测试运行器。
为了使事情有意义,您还需要不同的 import 语句,因为两个框架都有 不同 的 @Mock 注释实现。
(使用这些特定于框架的测试运行器的要点是它们负责使用特定于框架的特殊注释初始化所有字段)。
所以:这里的区别很简单:第一个示例是使用 Mockito 框架编写的,第二个使用 PowerMock。
现在,使用其中的哪一个?
答:莫基托。
为什么?不知何故,一个丑陋的事实是:PowerMock-one 基本上是在求救。它说“被测类设计不当,请修复”。含义:作为开发人员,您可以编写“易于测试”的代码,也可以编写“难以测试”的代码。许多人做第二种:他们编写难以测试的代码。然后,PowerMock(ito) 提供了 仍然 测试该代码的方法。
PowerMock(ito) 使您能够模拟(从而控制)对 静态 方法和
new()
的调用。为了实现这一点,PowerMock(ito) 操纵 被测 代码的字节码。这对于小型代码库来说完全没问题,但是当您面对数百万行生产代码和数千个单元测试时,情况就完全不同了。我已经看到许多 PowerMock 测试无缘无故失败,数小时后才发现……其他地方的一些“静态”东西被改变了,并且以某种方式影响了不同的 PowerMock 静态/新驱动测试用例。
在某个时候,我们的团队做出了一个有意识的决定:当您编写新代码时,您只能使用 PowerMock 对其进行测试……这是不可接受的。从那时起,我们只创建了 Mockito 测试用例,从那以后我们再也没有看到类似的怪异问题困扰我们 PowerMock。
使用 PowerMock 的唯一可接受的原因是当您想要测试您不想修改的现有(可能是第 3 方)代码时。但是当然,测试这样的代码有什么意义呢?当您无法修改该代码时,为什么测试会突然失败?