简体   繁体   English

Mocking 无效单元测试 Mockito

[英]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字段是staticprivate且具有硬编码依赖项。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM