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

Pet*_*ete 61 static mocking void mockito powermock

我的项目中有一些静态的util方法,其中一些只是传递或抛出异常.关于如何模拟具有除void之外的返回类型的静态方法,有很多例子.但是我如何模拟一个将void返回到" doNothing()" 的静态方法?

非void版本使用以下代码行:

@PrepareForTest(StaticResource.class)
Run Code Online (Sandbox Code Playgroud)

...

PowerMockito.mockStatic(StaticResource.class);
Run Code Online (Sandbox Code Playgroud)

...

Mockito.when(StaticResource.getResource("string")).thenReturn("string");
Run Code Online (Sandbox Code Playgroud)

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

有任何想法吗?

一个解决方法可能是让所有静态方法返回一些Boolean成功,但我不喜欢变通方法.

Jus*_*owe 75

您可以存根这样的静态void方法:

PowerMockito.doNothing().when(StaticResource.class, "getResource", anyString());
Run Code Online (Sandbox Code Playgroud)

虽然我不确定你为什么会这么麻烦,因为当你调用mockStatic(StaticResource.class)时,StaticResource中的所有静态方法都默认为stubbed

更有用的是,您可以捕获传递给StaticResource.getResource()的值,如下所示:

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

然后你可以像这样评估传递给StaticResource.getResource的String:

String resourceName = captor.getValue();
Run Code Online (Sandbox Code Playgroud)

  • 能够做到这一点非常酷,因为它可以让你做一些事情,比如模拟 Thread.sleep(long millis) 睡眠不同的时间/更少的时间/根本没有时间! (2认同)

Bri*_*ice 34

您可以像在实际实例上使用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
Run Code Online (Sandbox Code Playgroud)

感谢Matt Lachman的评论,请注意,如果在模拟创建时未更改默认答案,则默认情况下模拟将不执行任何操作.因此,编写以下代码相当于不编写它.

doNothing().doThrow(Exception.class).when(StaticResource.class);
StaticResource.getResource("string");
Run Code Online (Sandbox Code Playgroud)

虽然如此,对于那些阅读测试的同事来说,对于这个特定的代码没有任何期望,这可能会很有趣.当然,这可以根据感知的可理解性进行调整.


顺便说一句,在我看来,如果你制作新的代码,你应该避免模拟静态代码.在Mockito,我们认为它通常暗示了糟糕的设计,可能会导致代码难以维护.虽然现有的遗留代码是另一个故事.

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

希望有所帮助.

问候

  • 不幸的是,这不起作用,因为 when() 只接受一个变量,而 StaticResource 是一种类型。(`StaticResource 无法解析为变量`) (2认同)

Viv*_* HJ 12

简单来说,想象一下,如果你想在线下模拟:

StaticClass.method();
Run Code Online (Sandbox Code Playgroud)

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

PowerMockito.mockStatic(StaticClass.class);
PowerMockito.doNothing().when(StaticClass.class);
StaticClass.method();
Run Code Online (Sandbox Code Playgroud)

  • 它适用于 StaticClass.class 的多个方法吗,例如 StaticClass.method(); StaticClass.method1(); StaticClass.method2(); (3认同)

小智 7

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

示例代码:

File file =PowerMockito.mock(File.class);
PowerMockito.doNothing().when(FileUtils.class,"forceMkdir",file);
Run Code Online (Sandbox Code Playgroud)