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

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

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

问题

以下是翻译好的内容:

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

@Autowired
private MockMvc mockMvc;

@MockBean
private InventoryService inventoryService;

private List<InventoryDTO> inventoryList;

@BeforeEach
void setup() {
    ...
}

@Test
@DisplayName("POST /inventory 测试 - 状态 200")
@WithMockUser(roles = {"PUBLISHER", "USER"})
void addItem() throws Exception {
    doReturn(inventoryList.get(0)).when(inventoryService).add(any());

    mockMvc.perform(
            MockMvcRequestBuilders.post("/inventory")
                    .content(asJsonString(inventoryList.get(0)))
                    .contentType(MediaType.APPLICATION_JSON)
                    .accept(MediaType.APPLICATION_JSON))
            .andDo(MockMvcResultHandlers.print())
            .andExpect(status().isOk())
            .andExpect(content().json("{'name':'test1','description':'test-1-description','price':10}"))
            .andReturn();
}

以下是被测试的控制器:

@RestController
public class InventoryController {

    private final InventoryService inventoryService;

    public InventoryController(InventoryService inventoryService) {
        this.inventoryService = inventoryService;
    }

    @GetMapping("/inventory")
    @ResponseBody 
    public List<InventoryDTO> allInventory(){
        return inventoryService.findAll();
    }

    @PostMapping("/inventory")
    @ResponseBody 
    public InventoryDTO addInventory(@RequestBody InventoryDTO inventoryDTO){
        return inventoryService.add(inventoryDTO);
    }
}

以下是异常信息:

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"])
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
    ...

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

英文:

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

@Autowired
private MockMvc mockMvc;

@MockBean
private InventoryService inventoryService;


private List&lt;InventoryDTO&gt; inventoryList;

@BeforeEach
void setup() {
    ...
}

@Test
@DisplayName(&quot;POST /inventory test - status 200&quot;)
@WithMockUser(roles = {&quot;PUBLISHER&quot;, &quot;USER&quot;})
void addItem() throws Exception {

    doReturn(inventoryList.get(0)).when(inventoryService).add(any());

    mockMvc.perform(
            MockMvcRequestBuilders.post(&quot;/inventory&quot;)
                    .content(asJsonString(inventoryList.get(0)))
                    .contentType(MediaType.APPLICATION_JSON)
                    .accept(MediaType.APPLICATION_JSON))
            .andDo(MockMvcResultHandlers.print())
            .andExpect(status().isOk())
            .andExpect(content().json(&quot;{&#39;name&#39;:&#39;test1&#39;,&#39;description&#39;:&#39;test-1-description&#39;,&#39;price&#39;:10}&quot;))
            .andReturn();
}

And here is the tested controller:

@RestController
public class InventoryController {

    private final InventoryService inventoryService;

    public InventoryController(InventoryService inventoryService) {
        this.inventoryService = inventoryService;
    }

    @GetMapping(&quot;/inventory&quot;)
    @ResponseBody public List&lt;InventoryDTO&gt; allInventory(){
        return inventoryService.findAll();
    }

    @PostMapping(&quot;/inventory&quot;)
    @ResponseBody public InventoryDTO addInventory(@RequestBody InventoryDTO inventoryDTO){
        return inventoryService.add(inventoryDTO);
    }

And the exception:

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)
 at [Source: (PushbackInputStream); line: 1, column: 72] (through reference chain: com.teamcompetencymatrix.www.dto.InventoryDTO[&quot;audit&quot;])

	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:72)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
	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:

确定