如何对"update user"终结点引发的异常进行单元测试?



我目前正在对Spring Boot CRUD RESTful API的端点进行单元测试,我有以下"按其id更新用户">端点,该端点由控制器和服务组成,以实现其逻辑:

更新控制器(主要是调用服务的逻辑并定义一些准则(:

@RestController
@RequestMapping("/users/{id}")
public class UpdateUserController {
@Autowired
UpdateUserService service;
@PutMapping
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<User> updateUser_whenPutUser(@RequestBody User user, @PathVariable Long id) {
return ResponseEntity.ok().body(service.updateUser(id, user));
}
}

更新服务

@Service
public class UpdateUserService {
@Autowired
UserRepository repository;
public User updateUser(Long id, User user) {
repository.findById(id)
.orElseThrow(() -> new UserNotFoundException(id));
user.setId(id);
return repository.save(user);
}
}

虽然到目前为止一切似乎都运行良好,但如果有人能告诉我我可以在上面的代码中改进什么,我将不胜感激。无论如何,我的控制器抛出异常单元测试是我似乎无法解决的问题:

@RunWith(SpringRunner.class)
@WebMvcTest(UpdateUserController.class)
public class UpdateUserControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
private UpdateUserService updateUserService;
@Test
public void updateUser_whenPutUser() throws Exception {
User user = new User();
user.setName("Test Name");
user.setId(89L);
given(updateUserService.updateUser(user.getId(), user)).willReturn(user);
ObjectMapper mapper = new ObjectMapper();
mvc.perform(put("/users/" + user.getId().toString())
.content(mapper.writeValueAsString(user))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("name", is(user.getName())));
}
@Test
public void should_throw_exception_when_user_doesnt_exist() throws Exception {
User user = new User();
user.setId(89L);
user.setName("Test Name");
Mockito.doThrow(new UserNotFoundException(user.getId())).when(updateUserService).updateUser(user.getId(), user);
mvc.perform(put("/users/" + user.getId().toString())
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isNotFound());
}
}

尽管updateUser_whenPutUser通过,但异常单元测试会导致:

java.lang.AssertionError: Status expected:<404> but was:<400>
Expected :404
Actual   :400

这意味着它获得 400 响应状态,而不是异常引发的预期404

奇怪的是,如果我将@WebMvcTest(UpdateUserController.class(更改为@WebMvcTest(UpdateUserService.class(,它就会通过,但随后我的控制器主单元测试失败。不知道为什么。

如果有人能帮忙,将不胜感激。

首先,您可以为测试注释提供预期的类型。喜欢这个

@Test(expected = NotFoundException.class)
public void test(){
...
}

你得到400而不是404的原因很难说。我认为这与status()方法有关。也许您可以提供更多的堆栈跟踪?或者我认为您需要调试测试以找出异常发生的位置。

我已经找到了解决方案:

它返回 400 响应状态错误的原因是没有发送任何消息正文

此特定端点需要在请求中以 JSON 编写消息正文:

@Test
public void should_throw_exception_when_user_doesnt_exist() throws Exception {
User user = new User();
user.setId(89L);
user.setName("Test Name");
Mockito.doThrow(new UserNotFoundException(user.getId())).when(updateUserService).updateUser(user.getId(), user);
ObjectMapper mapper = new ObjectMapper();
mvc.perform(put("/users/" + user.getId().toString())
.content(mapper.writeValueAsString(user))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isNotFound());
}

最新更新