猿问

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

我在尝试对函数调用进行单元测试时遇到问题。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());

        }

    }


牧羊人nacy
浏览 151回答 2
2回答

梦里花落0921

如果您只是想捕获参数并以某种方式处理/验证它们,请不要使用 doAnswer。Mockito 有一个定义的功能,称为ArgumentCaptor专为此而设计。通过使用它,您将不需要像您那样与 void 方法讨价还价:@Mock private MessageProducer messageProducer;@Captor private ArgumentCaptor<Event> eventCaptor;@Captor private ArgumentCaptor<Long> longCaptor;@InjectMocksprivate MigrationRequestServiceImpl migrationRequestService;@Testpublic void sendRetriggerRequest() throws Exception {&nbsp; &nbsp;// When&nbsp; &nbsp;migrationRequestService.retriggerRequest(emsRetriggerRequest);&nbsp; &nbsp;// Then&nbsp; &nbsp;verify(messageProducer).sendMessage(eventCaptor.capture(), longCaptor.capture());&nbsp; &nbsp;Event e = eventCaptor().getValue();&nbsp; &nbsp;Long l = longCaptor().getValue();}

胡子哥哥

实际上我不想对参数做任何事情,我只需要跳过这个方法调用。我只是将 doAnswer 与一些伪代码一起使用,因为 doNothing() 或 doThrow() 不适用于此方法。但是我能够解决这个问题。被注入 Mocks (MigrationRequestServiceImpl) 的类的自动装配组件 (eventsConfigProperties) 之一没有在测试类中被模拟!感谢@daniu 指出这一点。来自 Mockito 的堆栈跟踪对调试问题不是很有帮助,它只是在方法调用时给出了一个空指针异常,这让我认为可能还有其他问题!为这个错误道歉,我的错,但谢谢你,很高兴知道 ArgumentCaptor,未来测试可能需要它!必须添加这个自动连接到 MigrationRequestService 类中的条目。// Test class@RunWith(MockitoJUnitRunner.class)public class RetriggerRequestTest {&nbsp; &nbsp; @Autowired&nbsp; &nbsp; EventsConfigProperties eventsConfigProperties;&nbsp; &nbsp; // Other declarations}
随时随地看视频慕课网APP

相关分类

Java
我要回答