[英]Mocking void unit tests with Mockito
Having had many issues in unit testing my application please help address my simplest issue - mocking void methods, per a few stack overflow articles and common references in articles .在对我的应用程序进行单元测试时遇到很多问题,请帮助解决我最简单的问题 - mocking 无效方法,根据一些堆栈溢出文章和文章中的常见参考。 My Java code in a JBPM application WorkItemHandler follows the pattern of
我在 JBPM 应用程序 WorkItemHandler 中的 Java 代码遵循以下模式
public class EmailNotificationWorkItemHandler() extends AbstractLogOrThrowWorkItemHandler {
private static Utils utils = new Utils() ;
public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
if (<condition>) {
utils.insertAmsErrors(<param>, <param>, <param>, <param>, <param>);
return;
}
....
try {
RequiredParameterValidator.validate(this.getClass(), workItem);
...
}
I have been trying to stub Utils and its insertAmsErrors method to test RequiredParameterValidator.validate used later in executeWorkItem.我一直在尝试存根 Utils 及其 insertAmsErrors 方法来测试稍后在 executeWorkItem 中使用的 RequiredParameterValidator.validate。 The references imply that the void call to utils and its insertAmsErrors method could be a very basic stub of
这些参考暗示对 utils 及其 insertAmsErrors 方法的无效调用可能是一个非常基本的存根
Utils mockUtils = mock(Utils.class);
doAnswer(new Answer<Void>() {
public Void answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
//Mock mock = (Mock) invocation.getMock(); Doesn't solve NPE
return null;
}
}).when(mockUtils).insertAmsErrors(any(), any(), any(), any(), any()); // NPE here
but the stub throws a null pointer exception at "NPE here".但存根在“NPE here”处抛出 null 指针异常。 Utils.insertAmsErrors signature is
Utils.insertAmsErrors 签名是
public void insertAmsErrors(String id, ErrorCode error, String errorMsg,
StackTraceElement [] stackTrace, long processId)
I also considered using a spy, per another answer in the same posting, but my unit test is not calling insertAmsErrors on an instance of Utils, but rather executeWorkItem in EmailNotificationWorkItemHandler is making such a call.根据同一帖子中的另一个答案,我还考虑过使用间谍,但我的单元测试不是在 Utils 的实例上调用 insertAmsErrors,而是 EmailNotificationWorkItemHandler 中的 executeWorkItem 正在进行这样的调用。
How should I correctly mock the Utils class and its insertAmsErrors method so that I can test RequiredParameterValidator.validate in executeWorkItem?我应该如何正确模拟 Utils class 及其 insertAmsErrors 方法,以便我可以在 executeWorkItem 中测试 RequiredParameterValidator.validate?
The problem is not related to the fact that you're mocking a void method.该问题与您 mocking 无效方法这一事实无关。 The problem lies in your usage of the
any()
method.问题在于您对
any()
方法的使用。
when(mockUtils).insertAmsErrors(any(), any(), any(), any(), any());
The 5th required parameter is of type long
and for this reason you should use the dedicated anyLong()
method for it instead.第 5 个必需参数是
long
类型,因此您应该使用专用的anyLong()
方法来代替它。 This applies to all primitive types: anyInt()
for int
parameters, anyBoolean()
for boolean
parameters and so on...这适用于所有原始类型:
anyInt()
用于int
参数, anyBoolean()
用于boolean
参数等等...
The reason behind this is that Mockito's any()
method returns null
by design , inducing a NPE when there is an attempt to unbox it.这背后的原因是 Mockito 的
any()
方法在设计上返回null
,在尝试拆箱时引发 NPE。 See this related answer for more details about it.有关它的更多详细信息,请参阅此相关答案。
(On a side note) Another potential problem could rise by the fact that your utils
field is static
, private
and with an hardcoded dependency. (旁注)另一个潜在的问题可能是由于您的
utils
字段是static
, private
且具有硬编码依赖项。 This is not a good target for stubbing and you should probably rethink this by making, for example, the field non-static and then injecting the dependency.这不是存根的好目标,您可能应该通过例如使字段非静态然后注入依赖项来重新考虑这一点。
public class EmailNotificationWorkItemHandler() extends AbstractLogOrThrowWorkItemHandler {
private Utils utils;
public EmailNotificationWorkItemHandler(Utils utils){
this.utils = utils;
}
...
}
This way you can pass the mocked object during your unit tests.这样您就可以在单元测试期间通过模拟的 object。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.