我在这里读了一些关于静态方法的文章,我想我理解滥用/过度使用静态方法会导致的问题。但是我并没有真正理解为什么很难模拟静态方法。
我知道其他的模拟框架,比如PowerMock,可以做到这一点,但是为什么Mockito不能呢?
我读了这篇文章,但作者似乎虔诚地反对静态这个词,也许是我的理解能力差。
一个简单的解释/链接就好了。
我在这里读了一些关于静态方法的文章,我想我理解滥用/过度使用静态方法会导致的问题。但是我并没有真正理解为什么很难模拟静态方法。
我知道其他的模拟框架,比如PowerMock,可以做到这一点,但是为什么Mockito不能呢?
我读了这篇文章,但作者似乎虔诚地反对静态这个词,也许是我的理解能力差。
一个简单的解释/链接就好了。
当前回答
我认为原因可能是模拟对象库通常通过在运行时动态创建类(使用cglib)来创建模拟。这意味着它们要么在运行时实现接口(如果我没有弄错的话,这就是EasyMock所做的),要么从类继承到mock(如果我没有弄错的话,这就是Mockito所做的)。这两种方法都不适用于静态成员,因为您不能使用继承重写它们。
模拟静态的唯一方法是在运行时修改类的字节代码,我认为这比继承要复杂一些。
这是我的猜测,无论如何……
其他回答
Mockito[3.4.0]可以模拟静态方法!
Replace mockito-core dependency with mockito-inline:3.4.0. Class with static method: class Buddy { static String name() { return "John"; } } Use new method Mockito.mockStatic(): @Test void lookMomICanMockStaticMethods() { assertThat(Buddy.name()).isEqualTo("John"); try (MockedStatic<Buddy> theMock = Mockito.mockStatic(Buddy.class)) { theMock.when(Buddy::name).thenReturn("Rafael"); assertThat(Buddy.name()).isEqualTo("Rafael"); } assertThat(Buddy.name()).isEqualTo("John"); } Mockito replaces the static method within the try block only.
作为对Gerold Broser的回答的补充,这里有一个带有参数的模拟静态方法的例子:
class Buddy {
static String addHello(String name) {
return "Hello " + name;
}
}
...
@Test
void testMockStaticMethods() {
assertThat(Buddy.addHello("John")).isEqualTo("Hello John");
try (MockedStatic<Buddy> theMock = Mockito.mockStatic(Buddy.class)) {
theMock.when(() -> Buddy.addHello("John")).thenReturn("Guten Tag John");
assertThat(Buddy.addHello("John")).isEqualTo("Guten Tag John");
}
assertThat(Buddy.addHello("John")).isEqualTo("Hello John");
}
在某些情况下,静态方法可能很难测试,特别是当它们需要被模拟时,这就是大多数模拟框架不支持它们的原因。我发现这篇博客文章在决定如何模拟静态方法和类方面非常有用。
Mockito返回对象,但静态意味着“类级别,而不是对象级别”,因此Mockito将为静态提供空指针异常。
我认为原因可能是模拟对象库通常通过在运行时动态创建类(使用cglib)来创建模拟。这意味着它们要么在运行时实现接口(如果我没有弄错的话,这就是EasyMock所做的),要么从类继承到mock(如果我没有弄错的话,这就是Mockito所做的)。这两种方法都不适用于静态成员,因为您不能使用继承重写它们。
模拟静态的唯一方法是在运行时修改类的字节代码,我认为这比继承要复杂一些。
这是我的猜测,无论如何……