Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
Ask Question
I cannot mock the private methods using mockito, but the method access specifier can be package or protected so i did that. but even after that i cannot achieve unit testing an exception throwing when the actual method contains several other protected method calls.
source:
public class ConsumeService {
private DataProcessService dataProcessService;
@JmsListener
public void getMessage(final Message message) throws InterruptedException {
if (message instanceof TextMessage) {
TextMessage textMessage = getTextMessage(message);
try {
Map<String, String> attributes = prepareInfo(textMessage);
dataProcessService.processRequestData(
message.getText(), attributes);
} catch (JMSException e) {
log.error("JMSException in message");
} catch (ResourceAccessException e) {
log.error("IOException in message");
} else {
log.error("message convertion failed!");
TextMessage getTextMessage(final Message message) {
return (TextMessage) message;
Map<String, String> prepareInfo(TextMessage message) throws JMSException {
return result;
Test method:
@ExtendWith(MockitoExtension.class)
public class ConsumeServiceTest {
@InjectMocks ConsumeService consumeService;
@Mock DataProcessService dataProcessService;
@Test
public void receiveMessageException() throws ResourceAccessException, JMSException{
TextMessage message = mock(TextMessage.class);
TextMessage textMessage = mock(TextMessage.class);
Map<String, String> mockMap = mock(HashMap.class);
when(consumeService.getTextMessage(message)).thenReturn(textMessage); //67 line
when(consumeService.prepareInfo(textMessage)).thenReturn(mockMap);
Mockito.lenient().
when(
dataProcessService.processRequestData(
textMessage.getText(), mockMap))
.thenThrow(ResourceAccessException.class);
assertThrows(
ResourceAccessException.class,
() -> this.consumeService.getMessage(message));
Error:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
at com.sample.rest.listner.service.ConsumeServiceTest.receiveMessageException(ConsumeServiceTest.java:67)
I absolutely have no clue how to resolve this. I am understanding the error is in stubing but i am not understanding how to fix this.
Secondly, an util method specifically useful for a class can be declared as private and in the same file. I do not see why mockito discourage private/static method mocking or testing in that way? Is it possible at all? i am using mockito with junit5
Update
Modified the test method
Updated test method:
@Test
public void receiveMessageException() throws ResourceAccessException, JMSException{
TextMessage message = mock(TextMessage.class);
Mockito.lenient().
when(
dataProcessService.processRequestData(
Mockito.anyString(), Mockito.any(Map.class)))
.thenThrow(ResourceAccessException.class);
assertThrows(
ResourceAccessException.class,
() -> this.consumeService.getMessage(message));
and now the error is
org.opentest4j.AssertionFailedError: Expected org.springframework.web.client.ResourceAccessException to be thrown, but nothing was thrown.
My assumption is it is failing in this line Map<String, String> attributes = prepareInfo(textMessage);
I am not sure. when i run the test in debug mode, i see attributes is an empty object.
How to throw this ResourceAccessException
–
–
–
Although it was not specified in the original post, I assume that the MissingMethodInvocationException is thrown by:
when(consumeService.getTextMessage(textMessage)).thenReturn(textMessage);
This happens because consumeService is not a mock but the object under test. If you want to stub methods of the ConsumeServiceTest class, you need to spy its instance.
Remarks:
It is discouraged to use @Spy and @InjectMocks on the same field. When this happens, it might be an indication that the class is violating the Single Responsibility Principle and you should break down that class into multiple independent classes.
@InjectMocks can be avoided if constructor or setter injection is used.
The stubbing of consumeService.getTextMessage(textMessage) seems unnecessary, a TextMessage instance is alredy the input of consumeService.getMessage
–
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.