为什么在模拟服务时,模拟的MVC测试会失败并引发异常?

huangapple go评论113阅读模式
英文:

Why mocked mvc test fails with exception when service is mocked?

问题

以下是翻译好的内容:

我不明白为什么这个测试会因为异常而失败?
服务类已被模拟...

  1. @Autowired
  2. private MockMvc mockMvc;
  3. @MockBean
  4. private InventoryService inventoryService;
  5. private List<InventoryDTO> inventoryList;
  6. @BeforeEach
  7. void setup() {
  8. ...
  9. }
  10. @Test
  11. @DisplayName("POST /inventory 测试 - 状态 200")
  12. @WithMockUser(roles = {"PUBLISHER", "USER"})
  13. void addItem() throws Exception {
  14. doReturn(inventoryList.get(0)).when(inventoryService).add(any());
  15. mockMvc.perform(
  16. MockMvcRequestBuilders.post("/inventory")
  17. .content(asJsonString(inventoryList.get(0)))
  18. .contentType(MediaType.APPLICATION_JSON)
  19. .accept(MediaType.APPLICATION_JSON))
  20. .andDo(MockMvcResultHandlers.print())
  21. .andExpect(status().isOk())
  22. .andExpect(content().json("{'name':'test1','description':'test-1-description','price':10}"))
  23. .andReturn();
  24. }

以下是被测试的控制器:

  1. @RestController
  2. public class InventoryController {
  3. private final InventoryService inventoryService;
  4. public InventoryController(InventoryService inventoryService) {
  5. this.inventoryService = inventoryService;
  6. }
  7. @GetMapping("/inventory")
  8. @ResponseBody
  9. public List<InventoryDTO> allInventory(){
  10. return inventoryService.findAll();
  11. }
  12. @PostMapping("/inventory")
  13. @ResponseBody
  14. public InventoryDTO addInventory(@RequestBody InventoryDTO inventoryDTO){
  15. return inventoryService.add(inventoryDTO);
  16. }
  17. }

以下是异常信息:

  1. org.springframework.web.util.NestedServletException: 请求处理失败;嵌套异常为 org.springframework.http.converter.HttpMessageConversionException: 类型定义错误:[simple type, class com.teamcompetencymatrix.www.dto.AuditDTO];嵌套异常为 com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 无法构造 `com.teamcompetencymatrix.www.dto.AuditDTO` 的实例(没有构造器,例如默认构造器):无法从对象值进行反序列化(没有委托或基于属性的构造器);位置:[源:(PushbackInputStream);行:1,列:72](通过引用链:com.teamcompetencymatrix.www.dto.InventoryDTO["audit"])
  2. at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
  3. ...

据我理解,Mockito 应该模拟服务类,而测试不会进入其中...
据我所知,审计员与控制器类无关。

英文:

I don't understand why this test fails with an exception?
The service class is mocked...

  1. @Autowired
  2. private MockMvc mockMvc;
  3. @MockBean
  4. private InventoryService inventoryService;
  5. private List&lt;InventoryDTO&gt; inventoryList;
  6. @BeforeEach
  7. void setup() {
  8. ...
  9. }
  10. @Test
  11. @DisplayName(&quot;POST /inventory test - status 200&quot;)
  12. @WithMockUser(roles = {&quot;PUBLISHER&quot;, &quot;USER&quot;})
  13. void addItem() throws Exception {
  14. doReturn(inventoryList.get(0)).when(inventoryService).add(any());
  15. mockMvc.perform(
  16. MockMvcRequestBuilders.post(&quot;/inventory&quot;)
  17. .content(asJsonString(inventoryList.get(0)))
  18. .contentType(MediaType.APPLICATION_JSON)
  19. .accept(MediaType.APPLICATION_JSON))
  20. .andDo(MockMvcResultHandlers.print())
  21. .andExpect(status().isOk())
  22. .andExpect(content().json(&quot;{&#39;name&#39;:&#39;test1&#39;,&#39;description&#39;:&#39;test-1-description&#39;,&#39;price&#39;:10}&quot;))
  23. .andReturn();
  24. }

And here is the tested controller:

  1. @RestController
  2. public class InventoryController {
  3. private final InventoryService inventoryService;
  4. public InventoryController(InventoryService inventoryService) {
  5. this.inventoryService = inventoryService;
  6. }
  7. @GetMapping(&quot;/inventory&quot;)
  8. @ResponseBody public List&lt;InventoryDTO&gt; allInventory(){
  9. return inventoryService.findAll();
  10. }
  11. @PostMapping(&quot;/inventory&quot;)
  12. @ResponseBody public InventoryDTO addInventory(@RequestBody InventoryDTO inventoryDTO){
  13. return inventoryService.add(inventoryDTO);
  14. }

And the exception:

  1. org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.teamcompetencymatrix.www.dto.AuditDTO]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.teamcompetencymatrix.www.dto.AuditDTO` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
  2. at [Source: (PushbackInputStream); line: 1, column: 72] (through reference chain: com.teamcompetencymatrix.www.dto.InventoryDTO[&quot;audit&quot;])
  3. at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
  4. at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
  5. at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)
  6. at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
  7. at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:72)
  8. at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
  9. at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)

As I understand mockito should mock the Service class, and the test doesn't go inside of it...
The Auditor has nothing to the Controller class as far as I know.

答案1

得分: 1

错误信息已经表明了一切:

> 无法构造com.teamcompetencymatrix.www.dto.AuditDTO的实例(没有像默认构造函数这样的创建者存在)

请求正文无法转换为DTO,请尝试为AuditDTO添加一个空构造函数和setter。

英文:

The error says it all:

> Cannot construct instance of
> com.teamcompetencymatrix.www.dto.AuditDTO (no Creators, like default
> constructor, exist)

The request body can't be transformed into the DTO, Try adding an empty constructor and setters to the AuditDTO

huangapple
  • 本文由 发表于 2020年10月25日 06:02:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/64518429.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定