Spring Boot 1.4 有许多优秀的特性,包括@DataJpaTest 注解,可以自动唤醒类路径嵌入式数据库以进行测试。据我所知,它不会在同一类的范围内与 TestRestTemplate 结合使用。
以下测试将不起作用:
@RunWith(SpringRunner.class)
@SpringBootTest
@DataJpaTest
public class PersonControllerTest {
private Logger log = Logger.getLogger(getClass());
private Category category;
@Autowired
private TestRestTemplate restTemplate;
@Autowired
private TestEntityManager entityManager;
@Before
public void init() {
log.info("Initializing...");
category = entityManager.persist(new Category("Staff"));
}
@Test
public void personAddTest() throws Exception {
log.info("PersonAdd test starting...");
PersonRequest request = new PersonRequest("Jimmy");
ResponseEntity<String> response = restTemplate.postForEntity("/Person/Add", request, String.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
log.info("PersonAdd test passed");
}
在测试启动期间会抛出一个异常:
Unsatisfied dependency expressed through field 'restTemplate':
No qualifying bean of type [org.springframework.boot.test.web.client.TestRestTemplate]
然后猜测切换到推荐的基于模拟的切片方法,但它在那里不起作用,因为 Controller 看起来像这样:
@RequestMapping(value="/Person/Add", method=RequestMethod.POST)
public ResponseEntity personAdd(@Valid @RequestBody PersonRequest personRequest,
Errors errors)
personValidator.validate(personRequest, errors):
if (errors.hasErrors())
return new ResponseEntity(HttpStatus.BAD_REQUEST);
personService.add(personRequest);
return new ResponseEntity(HttpStatus.OK);
}
...正如文档所建议的那样,模拟 personService
很容易,但是如何处理在这种情况下不可模拟的 errors
对象呢?据我所知,没有办法模拟它,因为它不是类字段或方法的返回值。
因此,我无法使用切片方法或集成方法测试上面的代码,因为 @DataJpaTest
不应与 Controller 一起使用。
有没有办法使用 Spring Boot 1.4 测试功能来测试具有这种架构的 Controller ?
最佳答案
您对 @DataJpaTest
的理解有点不对劲。来自文档“可以在测试仅关注 JPA 组件时使用”。如果你想测试你的 Controller 层,你不想使用这个注释,因为没有任何 WebMvc 组件被加载到应用程序上下文中。您反而想使用 @WebMvcTest
并让它使用您正在测试的 @Controller
。
@RunWith(SpringRunner.class)
@WebMvcTest(PersonController.class)
public class PersonControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
PersonValidator personValidator;
@MockBean
PersonService personService;
@Test
public void personAddTest() throws Exception {
String content = "{\"name\": \"Jimmy\"}";
mockMvc.perform(post("/Person/Add").contentType(MediaType.APPLICATION_JSON).characterEncoding("UTF-8")
.accept(MediaType.APPLICATION_JSON).content(content)).andExpect(status().isOk());
}
@Test
public void personAddInvalidTest() throws Exception {
String content = "{\"noname\": \"Jimmy\"}";
mockMvc.perform(post("/Person/Add").contentType(MediaType.APPLICATION_JSON).characterEncoding("UTF-8")
.accept(MediaType.APPLICATION_JSON).content(content)).andExpect(status().isBadRequest());
}
}
不确定您是如何连接 validator 和服务的,所以假设您是自动连接它们的。
@Controller
public class PersonController {
private PersonValidator personValidator;
private PersonService personService;
public PersonController(PersonValidator personValidator, PersonService personService) {
this.personValidator = personValidator;
this.personService = personService;
}
@RequestMapping(value = "/Person/Add", method = RequestMethod.POST)
public ResponseEntity<String> personAdd(@Valid @RequestBody PersonRequest personRequest, Errors errors) {
personValidator.validate(personRequest, errors);
if (errors.hasErrors()) {
return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
}
personService.add(personRequest);
return new ResponseEntity<String>(HttpStatus.OK);
}
}
示例 PersonRequest
因为我不知道里面还有什么。请注意名称上的一个验证是 @NotNull
,因为我想要一种方法来展示如何使用 Errors
对象。
public class PersonRequest {
@NotNull
private String name;
public PersonRequest() {
}
public PersonRequest(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
关于java - Spring Boot 1.4 - 如何使用验证来测试 Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38961112/