JUnit测试中CrudRepository save()返回对象调用方法空指针问题解决
问题分析与解决方案
核心问题
你遇到的NullPointerException原因很明确:
OrderEvent是Mock对象,默认所有方法返回null,哪怕你让save()返回这个Mock对象,调用它的getEventId()还是会返回null- 你写的
when(orderEventHistoryRepository.save(orderEvent).getEventId()).thenReturn(eventId);是错误的Mockito链式打桩写法,Mockito不支持这种直接链式的存根方式
修复步骤
删除错误的链式打桩代码
直接删掉这行报错的代码,它完全多余且写法错误:when(orderEventHistoryRepository.save(orderEvent).getEventId()).thenReturn(eventId);给Mock的OrderEvent对象打桩getEventId()方法
在给Repository的save()方法打桩前,先让你的MockorderEvent对象的getEventId()返回指定的eventId:when(orderEvent.getEventId()).thenReturn(eventId);确保Repository的save()打桩正确
保留这行代码,让save()返回已经打好桩的orderEvent:when(orderEventHistoryRepository.save(any(OrderEvent.class))).thenReturn(orderEvent);
额外需要修正的小问题
你的测试代码里还有几个拼写/变量名错误,不修正会直接导致测试失败:
myMessage.class应该改为MyMessage.class(类名首字母需大写)omsMessage应该改为myMessage(变量名要和你定义的一致)- 待测试代码里的
myMessage myMessage应该改为MyMessage myMessage(类名首字母需大写)
修正后的测试方法关键代码片段
@Test public void processOrderSchedulingSuccessTest() throws Exception { ConsumerRecord<String, String> consumerRecord = mock(ConsumerRecord.class); String messageValue = "{\"action\":\"SCHEDULE_ORDER\", \"payload\":{\"orderId\":\"12345\", \"orderItemIds\": [\"1\", \"2\", \"3\"]}}"; MyMessage myMessage = mock(MyMessage.class); OrderEvent orderEvent = mock(OrderEvent.class); Long orderItemId = 1L; Long eventId = 67890L; when(consumerRecord.value()).thenReturn(messageValue); // 修正类名大小写 when(objectMapper.readValue(consumerRecord.value(), MyMessage.class)).thenReturn(myMessage); // 修正变量名 when(commonUtils.getOrderEvent(myMessage, orderItemId, OrderEventCode.ORDER_SCHEDULED)).thenReturn(orderEvent); // 给OrderEvent的getEventId打桩 when(orderEvent.getEventId()).thenReturn(eventId); // 让save返回打好桩的orderEvent when(orderEventHistoryRepository.save(any(OrderEvent.class))).thenReturn(orderEvent); assertDoesNotThrow(() -> orderSchedulingService.processOrderScheduling(consumerRecord)); verify(orderEventHistoryRepository, times(3)).save(any(OrderEvent.class)); // 注意这里应该是times(3),因为orderItemIds有3个元素 //other assertions }
注意:原测试里的verify(orderEventHistoryRepository, times(1))要改为times(3),因为待测试代码会循环处理3个orderItemId,调用3次save()。
内容的提问来源于stack exchange,提问作者kickd16
相关产品推荐
相关产品推荐

