Java RESTAPI控制器的单元测试
我正在尝试使用mockito对spring控制器进行测试,但它不起作用 这是我的控制器:Java RESTAPI控制器的单元测试,java,spring,rest,spring-mvc,mockito,Java,Spring,Rest,Spring Mvc,Mockito,我正在尝试使用mockito对spring控制器进行测试,但它不起作用 这是我的控制器: @RestController public class CandidateController { private static final Logger log = LoggerFactory.getLogger(CandidateController.class); private CandidateService candidateService; @Autowired
@RestController
public class CandidateController {
private static final Logger log = LoggerFactory.getLogger(CandidateController.class);
private CandidateService candidateService;
@Autowired
public CandidateController(CandidateService candidateService) {
this.candidateService = candidateService;
}
@GetMapping("/candidates")
public ResponseEntity<List<Candidate>> getAllCandidates() {
List<Candidate> candidates = candidateService.findAll();
log.info("Candidates list size = {}", candidates.size());
if (candidates.size() == 0) {
return ResponseEntity.noContent().build();
}
return ResponseEntity.ok(candidates);
}
@GetMapping("/candidates/{id}")
public ResponseEntity<Candidate> getCandidateById(@PathVariable int id) {
Candidate candidate = candidateService.findById(id);
if (candidate != null) {
return ResponseEntity.ok(candidate);
} else {
log.info("Candidate with id = {} not found", id);
return ResponseEntity.notFound().build();
}
}
@GetMapping("/candidates/name/{name}")
public ResponseEntity<List<Candidate>> getCandidatesWhereNameLike(@PathVariable String name) {
List<Candidate> candidates = candidateService.findByLastNameLike("%" + name + "%");
log.info("Candidates by name list size = {}", candidates.size());
if (candidates.isEmpty()) {
return ResponseEntity.noContent().build();
}
return ResponseEntity.ok(candidates);
}
@PostMapping("/candidates/create")
public ResponseEntity<Object> postCandidate(@Valid @RequestBody Candidate candidate) {
Candidate newCandidate = candidateService.save(candidate);
if (newCandidate != null) {
URI location = ServletUriComponentsBuilder
.fromCurrentRequest()
.path("/{id}")
.buildAndExpand(newCandidate.getId())
.toUri();
return ResponseEntity.created(location).build();
} else {
log.info("Candidate is already existing or null");
return ResponseEntity.unprocessableEntity().build();
}
}
@PutMapping("/candidates/{id}")
public ResponseEntity<Object> updateCandidate(@PathVariable int id, @RequestBody Candidate candidate) {
candidateService.update(candidate, id);
candidate.setId(id);
return ResponseEntity.noContent().build();
}
@DeleteMapping("/candidates/{id}")
public ResponseEntity<Void> deleteCandidate(@PathVariable int id) {
candidateService.deleteById(id);
return ResponseEntity.noContent().build();
}
我期待着一个404未找到的响应,但我得到了一个204无内容的响应 ResponseEntity.noContent()返回204个代码,因此如果希望控制器返回404,则应将控制器类更改为返回ResponseEntity.notFound()我将尝试给您一些指导原则,可能会对您有所帮助:
@Test
public void findAll() {
...
}
创建一个更具建议性的名称,该名称还包括您正在操作的资源
@Test
public void shouldGetCandidatesList() {
...
}
或
@DeleteMapping("/candidates/{id}")
public ResponseEntity<Void> deleteCandidate(@PathVariable int id) {
try{
candidateService.deleteById(id);
} catch(ResourceNotFoundException e) {
ResponseEntity.notFound().build()
}
return ResponseEntity.noContent().build();
}
请调整get端点的测试,以同时检查JSON主体。如果测试仅测试端点返回某个响应主体时的状态,则仅完成了一半
还请检查一些有关如何构造端点的文档。您在这里所做的可能是工作和编译,但这并不意味着它是正确的。我指的是(“/candidates/name/{name}”,“/candidates/create”)。感谢您的回答:) 现在我将控制器更改为:
@DeleteMapping("/candidates/{id}")
public ResponseEntity<Void> deleteCandidate(@PathVariable int id) {
try {
candidateService.deleteById(id);
} catch (ResourceNotFoundException e) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.noContent().build();
}
但是当删除候选项时应该返回404不返回任何内容,我期待的是404
@试验 public void应在DeleteCandidatedOnExist()引发异常时返回NoContentWhen{
Candidate candidate = getATestCandidate();
doNothing().when(candidateService).deleteById(anyInt());
mockMvc.perform(
delete("/candidates/{id}", candidate.getId())
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isNoContent());
}
谢谢!@IoanM我也编辑了我的上一个anwser,一切都很好,除了一个小问题:)请检查我的编辑以进行删除测试。当你想从你的控制器返回404时,你应该指示candidateService抛出ResourceNotFoundException。先生,我添加了try{candidateService.deleteById(id)}catch(ResourceNotFoundException e){..到我的控制器,但我不知道如何在测试中检查它,因为它是无效的。我正在做:doNothing()。when(candidateService).deleteById(anyInt());对吗?请阅读我的文章的结尾,因为我在看到您的问题后编辑了它。when(candidateService.deleteById(anyInt())。然后抛出(new ResourceNotFoundException());这是如何设置服务以引发异常,然后检查未找到的异常..我不知道我何时尝试引发异常,但它不起作用,无论如何我是这样做的doThrow(new ResourceNotFoundException(candidate.getId()).when(candidateService).deleteById(anyInt());很好,谢谢你抽出时间,再次非常感谢
@Test
public void findAll() {
...
}
@Test
public void shouldGetCandidatesList() {
...
}
@Test
public void shouldReturn404NotFoundWhenGetCandidateByIdAndItDoesntExist() {
...
}
@DeleteMapping("/candidates/{id}")
public ResponseEntity<Void> deleteCandidate(@PathVariable int id) {
try{
candidateService.deleteById(id);
} catch(ResourceNotFoundException e) {
ResponseEntity.notFound().build()
}
return ResponseEntity.noContent().build();
}
@Test
public void shouldReturnNotFoundWhenGetCandidateByNonExistingId() {
//the Arrange part in your test
doThrow(new ResourceNotFoundException(candidate.getId())).when(candidateService).deleteById(anyInt());
//call mockMvc
//assert not found using the MockMvcResultMatchers
}
@DeleteMapping("/candidates/{id}")
public ResponseEntity<Void> deleteCandidate(@PathVariable int id) {
try {
candidateService.deleteById(id);
} catch (ResourceNotFoundException e) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.noContent().build();
}
@Test
public void shouldDeleteCandidate() throws Exception {
Candidate candidate = getATestCandidate();
doNothing().when(candidateService).deleteById(candidate.getId());
mockMvc.perform(
delete("/candidates/{id}", candidate.getId())
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isNoContent());
}
Candidate candidate = getATestCandidate();
doNothing().when(candidateService).deleteById(anyInt());
mockMvc.perform(
delete("/candidates/{id}", candidate.getId())
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isNoContent());
}