Mockito - 如何回答自定义对象

时间:2016-09-18 10:54:31

标签: java spring testing spring-boot mockito

尝试像这样测试结构:

@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);
}

Errors对象是由框架而不是我传递的,所以除了使用像Mockito这样的东西之外,没有更好的方法来改变它的测试行为。 {1}}:

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()); } 仍然返回errors.hasErrors(),尽管在false测试块上,由于HTTP状态doAnswer,断言失败。我希望OK对象在Errors调用后立即成为具有指定行为的间谍,但似乎我做错了。

那么,如何使用Mockito .validate()返回自定义对象?

2 个答案:

答案 0 :(得分:2)

不要在测试中使用postForEntity,因为这使它成为框架本身的集成测试,加上您正在测试的实际类。

只需创建自己的Errors对象,这可能是也可能不是模拟对象。如果它是模拟,那么你可以按如下方式设置它。

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

然后你的测试看起来像这样。

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

答案 1 :(得分:1)

仅当代码块使用间谍doReturn(true).when(errors).hasErrors()实例时,

errors才有效。如果将返回的Error引用分配给变量,则mock应该起作用:

errors = testValidator.validate(request, errors);

您将添加此作业仅用于测试目的,但它也有利于代码可读性;它强烈表示在errors方法中修改了validate实例。

更新:您可以包装验证程序以返回错误,而不是侦察包装的验证程序:

public class ValidatorWrapper {
    public Errors validate(TestRequest request, Errors errors) {
        testValidator.validate(request, errors);
        return errors;
    }
}

测试代码类似于:

controller.setValidatorWrapper(spiedValidatorWrapper);
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(spiedValidatorWrapper).validate(any(), any());
 //rest of the test

这应该可以解决问题。