为了账号安全,请及时绑定邮箱和手机立即绑定

模拟 void 方法返回空指针异常

模拟 void 方法返回空指针异常

牧羊人nacy 2023-06-08 14:37:58
我在尝试对函数调用进行单元测试时遇到问题。messageProducer.sendMessage()即使已存根,调用也会因 void 方法调用而失败。请在下面找到我的代码的简化快照。我正在使用 doAnswer() 存根来模拟 void 方法(基于 StackOverflow 上的早期答案)。我什至尝试了其他选项doThrow()和doNothing()存根,但在调用存根方法时它们也会因相同的 NPE 而失败 :(。感谢有人可以提出解决方案/解决方法。非常感谢。测试类// Test class@RunWith(MockitoJUnitRunner.class)public class RetriggerRequestTest {    @Mock    private MessageProducer messageProducer;     @InjectMocks    private MigrationRequestServiceImpl migrationRequestService;     @Before    public void init() {        MockitoAnnotations.initMocks(this);    }    @Test    public void sendRetriggerRequest() throws Exception {        // Below two stubbings also not Work, NPE encountered!        //doNothing().when(messageProducer).sendMessage(any(), anyLong());        //doThrow(new Exception()).doNothing().when(messageProducer).sendMessage(any(), anyLong());        doAnswer(new Answer<Void>() {            public Void answer(InvocationOnMock invocation) {                Object[] args = invocation.getArguments();                System.out.println("called with arguments: " + Arrays.toString(args));                return null;            }        }).when(messageProducer).sendMessage(any(EMSEvent.class), anyLong());        try {            // Gets Null pointer exception            migrationRequestService.retriggerRequest(emsRetriggerRequest);        }        catch (Exception ex) {            fail(ex.getMessage());        }    }
查看完整描述

2 回答

?
梦里花落0921

TA贡献1772条经验 获得超5个赞

如果您只是想捕获参数并以某种方式处理/验证它们,请不要使用 doAnswer。Mockito 有一个定义的功能,称为ArgumentCaptor专为此而设计。通过使用它,您将不需要像您那样与 void 方法讨价还价:


@Mock private MessageProducer messageProducer;


@Captor private ArgumentCaptor<Event> eventCaptor;

@Captor private ArgumentCaptor<Long> longCaptor;


@InjectMocks

private MigrationRequestServiceImpl migrationRequestService;


@Test

public void sendRetriggerRequest() throws Exception {

   // When

   migrationRequestService.retriggerRequest(emsRetriggerRequest);


   // Then

   verify(messageProducer).sendMessage(eventCaptor.capture(), longCaptor.capture());


   Event e = eventCaptor().getValue();

   Long l = longCaptor().getValue();

}


查看完整回答
反对 回复 2023-06-08
?
胡子哥哥

TA贡献1825条经验 获得超6个赞

实际上我不想对参数做任何事情,我只需要跳过这个方法调用。我只是将 doAnswer 与一些伪代码一起使用,因为 doNothing() 或 doThrow() 不适用于此方法。


但是我能够解决这个问题。被注入 Mocks (MigrationRequestServiceImpl) 的类的自动装配组件 (eventsConfigProperties) 之一没有在测试类中被模拟!感谢@daniu 指出这一点。


来自 Mockito 的堆栈跟踪对调试问题不是很有帮助,它只是在方法调用时给出了一个空指针异常,这让我认为可能还有其他问题!


为这个错误道歉,我的错,但谢谢你,很高兴知道 ArgumentCaptor,未来测试可能需要它!


必须添加这个自动连接到 MigrationRequestService 类中的条目。


// Test class

@RunWith(MockitoJUnitRunner.class)

public class RetriggerRequestTest {

    @Autowired

    EventsConfigProperties eventsConfigProperties;


    // Other declarations

}


查看完整回答
反对 回复 2023-06-08
  • 2 回答
  • 0 关注
  • 150 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信