Issue
while mocking the controller class, i am unable to cover the catch block in my unit testing,
here is the code - Controller Class -
public ResponseEntity<ResponseSentence> getText(@RequestBody Text text) throws IOException {
try {
return new ResponseEntity<>(serviceImpl.getText(text), HttpStatus.OK);
} catch (IOException e) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
}
this is my test class
@Autowired
private MockMvc mockMvc;
@MockBean
private Service service;
@MockBean
private ServiceImpl serviceImp;
@Autowired
private ObjectMapper objectMapper;
@Test
void getText() throws Exception {
Text text = new Text();
text.setText("");
//given(service.getText(text)).willThrow(new IOException("boom"));
when(serviceImp.getText(text)).thenThrow(new IOException());
ResultActions response = mockMvc.perform(post("/opennlp/v1/sentence")
.contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(text)));
response.andDo(print()).
andExpect(status().isBadRequest());
Mockito.verify(serviceImp).getText(any());
}
while code coverage the catch block is not covered.
Solution
The cause of your problem is the fact that the Text
instance used in your test method and the Test
instance present in the actual controller code present when running the test are two separate instances and the Text
class does not have an equals
method defined. In the test method you're creating an object using the constructor (new
) and in the controller method a separate instance of the object is passed, created by Jackson ObjectMapper
. Since no equals
method is defined, when Mockito compares the objects they do not match and the mocked behavior is not executed.
You can either define the equals
method in the Text
class (remembering about the equals and hashCode methods contract) or use an argument matcher when defining the behavior using Mockito, depending on what you'd like to test:
when(serviceImp.getText(any()))
.thenThrow(new IOException());
when(serviceImp.getText(argThat(value => value.getText().isEmpty())))
.thenThrow(new IOException());
String someValue = "custom value";
text.setText(someValue);
when(serviceImp.getText(argThat(value => someValue.equals(value.getText()))))
.thenThrow(new IOException());
Answered By - Jonasz
Answer Checked By - Timothy Miller (JavaFixing Admin)