我在尝试单元测试函数调用时遇到了一个问题。尽管调用已被存根,但由于无效方法调用MessageProducer.sendMessage()
而失败。
请在下面找到我的代码的简化快照。我正在使用do答案()存根来模拟空方法(基于StackOverflow上的早期答案)。
我甚至尝试了其他选项的doThrow()
和doNot()
存根,但当调用存根方法时,它们也会在相同的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());
}
}
正在测试的实现类,来自该类的存根方法调用抛出NPE,如代码注释所示
@Service
@Transactional
public class MigrationRequestServiceImpl implements MigrationRequestService {
@Autowired
MessageProducer messageProducer;
@Override
public void retriggerRequest(EMSRetriggerRequestData emsRetriggerRequestData) throws EMSException {
// Does a bunch of things
submitTaskScheduledEventsToQueue(taskList);
}
private void submitTaskScheduledEventsToQueue(List<Task> taskList) {
System.out.println("Debugging 1...");
taskList.stream().forEach(task -> {
System.out.println("Debugging 2...");
Map<String, Object> detailsMap = new HashMap<String, Object>();
EMSEvent event = new EMSEvent(EMSEventType.TASK_SCHEDULED);
event.setDetails(detailsMap);
LOGGER.info(ContextRetriever.getServiceContext(), ContextRetriever.getRequestContext(), "*** Re-submitting Task: *** " + task.getId());
// ****Gives a null pointer exception here****
messageProducer.sendMessage(event, eventsConfigProperties.getScheduledEventDelay());
});
System.out.println("Debugging 3...");
}
}
自动连接类,该类被注入测试类,其方法是抛出NPE
@Service
public class MessageProducer {
private static final Logger logger = LoggerFactory.getLogger(MessageProducer.class);
private final RabbitTemplate rabbitTemplate;
@Autowired
public MessageProducer(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
public void sendMessage(EMSEvent emsEvent, Long delay) {
// code to send message to RabbitMQ here
}
}
谢谢你Maciej的回答。实际上我不想对参数做任何事情,我只需要跳过这个方法调用。我只是用了一些假代码的do答案,因为doNo()或doThrow()不适用于这个方法。
不过,我还是解决了这个问题。正在注入模拟(MigrationRequestServiceImpl)的类的一个自动连接组件(EventsConfigProperty)在测试类中未被模拟!感谢@daniu指出这一点。
Mockito的堆栈跟踪对调试这个问题没有太大帮助,它只是在方法调用上出现了一个空指针异常,这让我觉得可能还有其他问题!
为这个错误道歉,我的错,但是谢谢你,很高兴了解ArgumentCaptor,将来可能需要它进行测试!
必须添加自动连接到MigrationRequestService类的条目。
// Test class
@RunWith(MockitoJUnitRunner.class)
public class RetriggerRequestTest {
@Autowired
EventsConfigProperties eventsConfigProperties;
// Other declarations
}
如果只是想捕获参数并以某种方式处理/验证它们,请不要使用doAnswer。Mockito有一个定义的特性,名为ArgumentCaptor
,就是专门为此设计的。通过使用它,你将不需要像现在这样讨价还价:
@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();
}
函数setUpMapIfNeeded()中的getFragmentManager返回。我把我的片段与activity_main.xml分开,这里是我的代码: activity_main.xml: fragment_main.xml: 这是我的*.Java文件: 我已尝试将getSupportFramentManager与Android.support.v4.app.DialogFragment支持
web.xml 应用程序-servlet.xml context.xml(在tomcat conf文件夹中) 谢谢你的建议和帮助。
问题内容: 当我尝试在片段上显示地图时,它返回空指针异常。我已将所有权限添加到清单中。我将片段文件附加为其XML文件和log cat Chatffragment.java 其XML LOGCAT 第55和70行是googleMap = mapFrag.getMap(); initilizeMap(); 问题答案: 您必须等到地图加载完毕…。 编辑 检查编辑代码,使用ChildFragmentMan
问题内容: 我正在为我的应用程序编写单元测试,我想知道Mockito框架是否有可能影响传递到返回无效类的方法中的对象。例如,调用一个包含方法的模拟验证类,该方法返回void,但通过作为参数传入的对象来跟踪各种更改和元数据。。 我为其他测试模拟了验证器类,但是对于这个测试,我需要模拟对不知道怎么做的cartItemsFilter对象的更改。 问题答案: 答案是肯定的,您可以,并且根据测试的需要,基本
我有下面的课,我试图测试。我遇到问题的方法是,因为我试图存根/模拟行为,然后在测试中验证行为。
我在玩C语言中的函数指针只是为了学习。我尝试调用一个空函数,并将其结果设置为int。 我从中得到的结果是: 在对它进行了一点研究之后,我意识到main正在函数()中打印printf语句中的字符数。为什么会这样?这是预期产出吗?