如何使用 PowerMock 模拟返回 void 的静态方法?

在我的项目中有一些静态 util 方法,其中一些只是传递或抛出异常。有很多关于如何模拟具有除 void 之外的返回类型的静态方法的示例。但是我怎样才能模仿一个静态方法,返回 void 只是“ doNothing()”?

非无效版本使用以下代码行:

@PrepareForTest(StaticResource.class)

...

PowerMockito.mockStatic(StaticResource.class);

...

Mockito.when(StaticResource.getResource("string")).thenReturn("string");

但是,如果应用于返回 voidStaticResources,则编译将抱怨 when(T)不适用于 void..。

有什么想法吗?

变通方法可能是让所有静态方法返回一些 Boolean以获得成功,但我不喜欢变通方法。

143158 次浏览

自 Mockito 3.4.0以来,引入了一个实验性的 API 来模拟静态方法。

下面的示例代码已经用 Mockito 4.3.1(testImplementation("org.mockito:mockito-inline:4.3.1)和 JUnit Jupiter 5.8.2、 OpenJDK 11进行了测试。

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;


import java.util.UUID;


public class StaticMockTest {


@Test
void showCaseStaticMock() {
try (MockedStatic<StaticMockTest> staticMock = Mockito.mockStatic(StaticMockTest.class)) {
staticMock.when(StaticMockTest::getUUIDValue).thenReturn("Mockito");
Assertions.assertEquals("Mockito", StaticMockTest.getUUIDValue());
}


// Regular UUID
UUID.fromString(StaticMockTest.getUUIDValue());
}


public static String getUUIDValue() {
return UUID.randomUUID().toString();
}
}

上一个答案,可能是 Mockito 1.x/2.x 和 Powermock 1.x/2. x

您可以像在真实实例中使用 Mockito 一样进行此操作。例如,您可以链接存根,以下行将使第一个调用什么也不做,然后第二个和未来的 getResources调用将抛出异常:

// the stub of the static method
doNothing().doThrow(Exception.class).when(StaticResource.class);
StaticResource.getResource("string");
    

// the use of the mocked static code
StaticResource.getResource("string"); // do nothing
StaticResource.getResource("string"); // throw Exception

感谢 Matt Lachman 的一句话,请注意,如果在模拟创建时没有更改默认答案,那么模拟在默认情况下将什么也不做。因此,编写下面的代码等同于不编写它。

doNothing().doThrow(Exception.class).when(StaticResource.class);
StaticResource.getResource("string");

尽管如此,对于阅读测试的同事来说,您对这个特定代码没有任何期望,这可能会很有趣。当然,这可以根据如何感知测试的 可以理解来调整。


顺便说一下,在我看来,如果您要编写新代码,应该避免模仿静态代码。在 Mockito,我们通常认为这是糟糕设计的暗示,可能导致代码维护性差。虽然现有的遗留代码是另一回事。

一般来说,如果您需要模拟私有或静态方法,那么这个方法做得太多,应该将其外部化在将被注入到测试对象中的对象中。

希望能帮上忙。

问候

您可以使用 票根这样的静态 void 方法:

PowerMockito.doNothing().when(StaticResource.class, "getResource", anyString());

虽然我不知道您为什么要这么麻烦,因为当您调用 仿静态(StaticResource.class)时,StaticResource 中的所有静态方法都是默认存根化的

更有用的是,您可以像下面这样捕获传递给 GetResource ()的值:

ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
PowerMockito.doNothing().when(
StaticResource.class, "getResource", captor.capture());

然后您可以像下面这样计算传递给 StaticResource.getResource 的 String:

String resourceName = captor.getValue();

简单来说, 想象一下,如果你想要在下面的行:

StaticClass.method();

然后编写下面几行代码来模仿:

PowerMockito.mockStatic(StaticClass.class);
PowerMockito.doNothing().when(StaticClass.class);
StaticClass.method();

模拟返回 void 的静态方法,例如 Fileutils.forceMKdir(File file),

示例代码:

File file =PowerMockito.mock(File.class);
PowerMockito.doNothing().when(FileUtils.class,"forceMkdir",file);