WildDev WildDev - 2 months ago 17
Java Question

Mockito - how to answer with custom object

Trying to test the construction like this:

@RequestMapping(value = "/test", method = POST)
public ResponseEntity test(@RequestBody TestRequest request, Errors errors) {

testValidator.validate(request, errors); // Spring Validator interface impl


if (errors.hasErrors())
return new ResponseEntity(HttpStatus.BAD_REQUEST);

return new ResponseEntity(HttpStatus.OK);
}


The
Errors
object is passed by framework and not by me, so there's no better way to change it's behaviour for the test except of using something like Mockito's
Answer
:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ExampleTest {

@Autowired
private TestRestTemplate testRestTemplate;

@MockBean
private TestValidator testValidator;

@Test
public void test() {

doAnswer(new Answer<Errors>() {

@Override
public Errors answer(InvocationOnMock invocation) throws Throwable {

Errors errors = spy((Errors) invocation.getArguments()[1]);
//errors.rejectValue("id", "id", "id rejected");

doReturn(true).when(errors).hasErrors();

return errors;
}

}).when(testValidator).validate(any(), any());

ResponseEntity re = testRestTemplate
.postForEntity("/test", new TestRequest(213L), String.class);

assertEquals(HttpStatus.BAD_REQUEST, re.getStatusCode());
}


... but the problem is
errors.hasErrors()
still returns
false
despite on
doAnswer
test block and the assertion fails because of HTTP status
OK
. I expect the
Errors
object will become the spy with specified behaviour right after
.validate()
call but seems I'm doing something wrong.

So, how to return a custom object using Mockito's
doAnswer
?

Answer

Don't use postForEntity in your test, because that makes it an integration test of the framework itself, plus the actual class that you're testing.

Just make your own Errors object, which may or may not be a mock. If it's a mock, then you can set it up as follows.

doReturn(true).when(mockErrors).hasErrors();

Then your test can look like this.

@Test
public void test() {
  ResponseEntity re = objectThatYoureTesting.test(mockTestRequest, mockErrors);
  assertEquals(HttpStatus.BAD_REQUEST, re.getStatusCode());
}