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

beq87vna  于 2023-01-02  发布在  其他
关注(0)|答案(4)|浏览(357)

我在我的项目中有一些静态util方法,其中一些只是传递或抛出异常。有很多例子是关于如何模拟一个返回类型不是void的静态方法。但是我如何模拟一个只返回void为"doNothing()"的静态方法呢?
非void版本使用以下代码行:

@PrepareForTest(StaticResource.class)

...

PowerMockito.mockStatic(StaticResource.class);

...

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

但是,如果应用于返回voidStaticResources,编译器将报告when(T)不适用于void ...
有什么想法吗?
一种变通方法可能是让所有静态方法返回一些Boolean以获得成功,但我不喜欢这种变通方法。

mbskvtky

mbskvtky1#

你可以stub一个静态void方法,如下所示:

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

尽管我不知道您为什么要这么麻烦,因为当您调用**mockStatic(StaticResource.class)时,StaticResource中的所有静态方法都默认为stub
更有用的是,您可以捕获传递给
StaticResource.getResource()**的值,如下所示:

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

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

String resourceName = captor.getValue();
3gtaxfhh

3gtaxfhh2#

从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的评论,请注意如果默认答案在mock创建时没有改变,那么mock在默认情况下什么也不做,因此编写下面的代码等同于不编写它。

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

尽管如此,对于阅读测试的同事来说,你对这个特定的代码没有任何期望,这可能是有趣的。当然,这可以根据对测试的理解程度来调整。
顺便说一句,在我看来,如果你在编写新代码,你应该避免嘲笑静态代码。在Mockito,我们认为这通常是一个坏设计的暗示,它可能会导致代码的可维护性很差。尽管现有的遗留代码是另一回事。
一般来说,如果您需要模拟私有或静态方法,那么这个方法做得太多了,应该在一个对象中外部化,该对象将被注入到测试对象中。
希望能有所帮助。
问候

cgh8pdjw

cgh8pdjw3#

简单地说,想象一下,如果你想模拟下面的行:

StaticClass.method();

然后你写下面几行代码来模拟:

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

wi3ka0sx4#

模拟为Fileutils.forceMKdir(File file),等返回void的静态方法
样本代码:

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

相关问题