如何在 Repository 中使用 mockito 测试 InternalServerError?
How to test InternalServerError using mockito in Repository?
我正在编写一个测试来测试 POST 方法在控制器中的失败情况。
它 returns 一个 415,我期待 500。我已经使用 mockito 模拟了响应。
控制器测试
@Test
@DisplayName("POST /customers - Failure")
void createProductShouldFail() throws Exception {
// Setup mocked service
when(customerService.save(any(Customer.class))).thenThrow(HttpServerErrorException.InternalServerError.class);
RequestBuilder requestBuilder = MockMvcRequestBuilders.post("/customers").accept(MediaType.APPLICATION_JSON)
.content("{\"name\":\"John\"}");
MvcResult result=mockMvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = result.getResponse();
// Validate the response code and content type
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR.value(), response.getStatus());
}
控制器
@PostMapping(path = "/customers")
public ResponseEntity<Customer> saveCustomer(@RequestBody Customer customer){
try {
// Create the new product
Customer savedCustomer = customerService.save(customer);
// Build a created response
return ResponseEntity
.created(new URI("/customers/" + savedCustomer.getId()))
.body(savedCustomer);
} catch (URISyntaxException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
错误:
HTTP Method = POST
Request URI = /customers
Parameters = {}
Headers = [Accept:"application/json", Content-Length:"15"]
Body = {"name":"John"}
Session Attrs = {}
Handler:
Type = com.prabhakar.customer.controller.CustomerController
Method = com.prabhakar.customer.controller.CustomerController#saveCustomer(Customer)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.HttpMediaTypeNotSupportedException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 415
Error message = null
Headers = [Accept:"application/json, application/*+json"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
org.opentest4j.AssertionFailedError:
Expected :500
Actual :415
但是 415-Unsupported Media Type 客户端错误响应代码。
我对这个方法使用了相同的负载,它有效。
@Test
@DisplayName("POST /customers - Success")
void createProductShouldSucceed() throws Exception {
// Setup mocked service
Customer mockCustomer = new Customer(1L, "John");
when(customerService.save(any(Customer.class))).thenReturn(mockCustomer);
this.mockMvc.perform(post("/customers")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"name\":\"John\"}"))
// Validate the response code and content type
.andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
//Validate returned json fields
.andExpect(jsonPath("$.id").value(1L))
.andExpect(jsonPath("$.name").value("John"));
}
Update I have added
@RestController
@EnableWebMvc
这会像模拟一样抛出错误但是代码在 mockmvc.perform
附近中断。
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.client.HttpServerErrorException$InternalServerError
我如何验证这是否有效。
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR.value(), response.getStatus());
可以参考Spring MVC Test Framework - Unsupported Media Type
您的控制器中可能缺少 @EnableWebMvc 注释。
编辑 - 评论:
而不是
RequestBuilder requestBuilder = MockMvcRequestBuilders.post("/customers").accept(MediaType.APPLICATION_JSON)
.content("{\"name\":\"John\"}");
MockHttpServletResponse response = result.getResponse();
// Validate the response code and content type
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR.value(),
response.getStatus());
尝试:
mockMvc.perform(requestBuilder)
.andExpect(status().isInternalServerError());
解决问题必须考虑两点:
首先,而不是使用.accept(MediaType.APPLICATION_JSON)
你必须使用.contentType(MediaType.APPLICATION_JSON)
.
Second,你必须考虑的另一件事是,如果你不处理异常(使用控制器建议或其他方式),你必须这样做,因为当您执行第一步时,您将收到以下错误:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.client.HttpServerErrorException$InternalServerError
我采取的解决方法是在 CustomerController
中使用 @ExceptionHandler
来测试您的代码(这不是执行此操作的最佳位置,具体取决于您在做什么。而是使用 @ ControllerAdvice。您可以在此处找到一些示例 https://www.baeldung.com/exception-handling-for-rest-with-spring).
下面是用于重新创建案例的完整代码。
Customer.class
public class Customer {
private Long id;
private String name;
public Customer(Long id, String name) {
this.id = id;
this.name = name;
}
// + getter and setter
}
CustomerController.class
@RestController
public class CustomerController {
private final CustomerService customerService;
public CustomerController(CustomerService customerService) {
this.customerService = customerService;
}
@PostMapping(path = "/customers")
public ResponseEntity<Customer> saveCustomer(@RequestBody Customer customer) {
try {
// Create the new product
Customer savedCustomer = customerService.save(customer);
// Build a created response
return ResponseEntity
.created(new URI("/customers/" + savedCustomer.getId()))
.body(savedCustomer);
} catch (URISyntaxException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
// Code used to avoid the error explained in the second step
@ExceptionHandler
public ResponseEntity<?> handlingInternalServerError(HttpServerErrorException.InternalServerError ex) {
// code to be executed when the exception is thrown (logs, ...)
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
CustomerService.class
@Service
public class CustomerService {
public Customer save(Customer customer) {
return customer;
}
}
CustomerControllerTest.class
@SpringBootTest
@AutoConfigureMockMvc
class CustomerControllerTest {
@MockBean
private CustomerService customerService;
@Autowired
private MockMvc mockMvc;
@Test
@DisplayName("POST /customers - Failure")
void saveCustomer() throws Exception {
Customer customerMock = new Customer(1L, "John");
// Setup mocked service
when(customerService.save(any(Customer.class))).thenThrow(HttpServerErrorException.InternalServerError.class);
RequestBuilder requestBuilder = post("/customers")
.content("{\"name\":\"John\"}")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = result.getResponse();
// Validate the response code and content type
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR.value(), response.getStatus());
}
}
注意: 此测试是使用 Java 8 和 JUnit5
执行的
根据您的评论得出的其他注意事项:
行。 @prabhakar-maity,根据您的情况,我的建议是使用@ExceptionHandler 或@ControllerAdvice 而不是try...catch。例如,您的控制器中有 6 个方法或多个控制器,并且想要处理相同的异常(内部服务器错误)和 return 相同的信息,因此您必须在每个方法中实现一个 try..catch ,在使用@ControllerAdive(多个控制器)或@ExceptionHandler(一个控制器)时,您可以在一个地方实现您的逻辑
查看此问题以获取更多信息LINK
我正在编写一个测试来测试 POST 方法在控制器中的失败情况。 它 returns 一个 415,我期待 500。我已经使用 mockito 模拟了响应。 控制器测试
@Test
@DisplayName("POST /customers - Failure")
void createProductShouldFail() throws Exception {
// Setup mocked service
when(customerService.save(any(Customer.class))).thenThrow(HttpServerErrorException.InternalServerError.class);
RequestBuilder requestBuilder = MockMvcRequestBuilders.post("/customers").accept(MediaType.APPLICATION_JSON)
.content("{\"name\":\"John\"}");
MvcResult result=mockMvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = result.getResponse();
// Validate the response code and content type
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR.value(), response.getStatus());
}
控制器
@PostMapping(path = "/customers")
public ResponseEntity<Customer> saveCustomer(@RequestBody Customer customer){
try {
// Create the new product
Customer savedCustomer = customerService.save(customer);
// Build a created response
return ResponseEntity
.created(new URI("/customers/" + savedCustomer.getId()))
.body(savedCustomer);
} catch (URISyntaxException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
错误:
HTTP Method = POST
Request URI = /customers
Parameters = {}
Headers = [Accept:"application/json", Content-Length:"15"]
Body = {"name":"John"}
Session Attrs = {}
Handler:
Type = com.prabhakar.customer.controller.CustomerController
Method = com.prabhakar.customer.controller.CustomerController#saveCustomer(Customer)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.HttpMediaTypeNotSupportedException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 415
Error message = null
Headers = [Accept:"application/json, application/*+json"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
org.opentest4j.AssertionFailedError:
Expected :500
Actual :415
但是 415-Unsupported Media Type 客户端错误响应代码。
我对这个方法使用了相同的负载,它有效。
@Test
@DisplayName("POST /customers - Success")
void createProductShouldSucceed() throws Exception {
// Setup mocked service
Customer mockCustomer = new Customer(1L, "John");
when(customerService.save(any(Customer.class))).thenReturn(mockCustomer);
this.mockMvc.perform(post("/customers")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"name\":\"John\"}"))
// Validate the response code and content type
.andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
//Validate returned json fields
.andExpect(jsonPath("$.id").value(1L))
.andExpect(jsonPath("$.name").value("John"));
}
Update I have added
@RestController
@EnableWebMvc
这会像模拟一样抛出错误但是代码在 mockmvc.perform
附近中断。
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.client.HttpServerErrorException$InternalServerError
我如何验证这是否有效。
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR.value(), response.getStatus());
可以参考Spring MVC Test Framework - Unsupported Media Type
您的控制器中可能缺少 @EnableWebMvc 注释。
编辑 - 评论:
而不是
RequestBuilder requestBuilder = MockMvcRequestBuilders.post("/customers").accept(MediaType.APPLICATION_JSON)
.content("{\"name\":\"John\"}");
MockHttpServletResponse response = result.getResponse();
// Validate the response code and content type
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR.value(),
response.getStatus());
尝试:
mockMvc.perform(requestBuilder)
.andExpect(status().isInternalServerError());
解决问题必须考虑两点:
首先,而不是使用
.accept(MediaType.APPLICATION_JSON)
你必须使用.contentType(MediaType.APPLICATION_JSON)
.Second,你必须考虑的另一件事是,如果你不处理异常(使用控制器建议或其他方式),你必须这样做,因为当您执行第一步时,您将收到以下错误:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.client.HttpServerErrorException$InternalServerError
我采取的解决方法是在 CustomerController
中使用 @ExceptionHandler
来测试您的代码(这不是执行此操作的最佳位置,具体取决于您在做什么。而是使用 @ ControllerAdvice。您可以在此处找到一些示例 https://www.baeldung.com/exception-handling-for-rest-with-spring).
下面是用于重新创建案例的完整代码。
Customer.class
public class Customer {
private Long id;
private String name;
public Customer(Long id, String name) {
this.id = id;
this.name = name;
}
// + getter and setter
}
CustomerController.class
@RestController
public class CustomerController {
private final CustomerService customerService;
public CustomerController(CustomerService customerService) {
this.customerService = customerService;
}
@PostMapping(path = "/customers")
public ResponseEntity<Customer> saveCustomer(@RequestBody Customer customer) {
try {
// Create the new product
Customer savedCustomer = customerService.save(customer);
// Build a created response
return ResponseEntity
.created(new URI("/customers/" + savedCustomer.getId()))
.body(savedCustomer);
} catch (URISyntaxException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
// Code used to avoid the error explained in the second step
@ExceptionHandler
public ResponseEntity<?> handlingInternalServerError(HttpServerErrorException.InternalServerError ex) {
// code to be executed when the exception is thrown (logs, ...)
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
CustomerService.class
@Service
public class CustomerService {
public Customer save(Customer customer) {
return customer;
}
}
CustomerControllerTest.class
@SpringBootTest
@AutoConfigureMockMvc
class CustomerControllerTest {
@MockBean
private CustomerService customerService;
@Autowired
private MockMvc mockMvc;
@Test
@DisplayName("POST /customers - Failure")
void saveCustomer() throws Exception {
Customer customerMock = new Customer(1L, "John");
// Setup mocked service
when(customerService.save(any(Customer.class))).thenThrow(HttpServerErrorException.InternalServerError.class);
RequestBuilder requestBuilder = post("/customers")
.content("{\"name\":\"John\"}")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = result.getResponse();
// Validate the response code and content type
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR.value(), response.getStatus());
}
}
注意: 此测试是使用 Java 8 和 JUnit5
执行的根据您的评论得出的其他注意事项: 行。 @prabhakar-maity,根据您的情况,我的建议是使用@ExceptionHandler 或@ControllerAdvice 而不是try...catch。例如,您的控制器中有 6 个方法或多个控制器,并且想要处理相同的异常(内部服务器错误)和 return 相同的信息,因此您必须在每个方法中实现一个 try..catch ,在使用@ControllerAdive(多个控制器)或@ExceptionHandler(一个控制器)时,您可以在一个地方实现您的逻辑
查看此问题以获取更多信息LINK