Spring引导使用@WebMvcTest进行单元测试 - 执行不会从控制器进入服务层并返回null而不会出错

问题描述 投票:0回答:2

我正在为我的春季启动应用程序的控制器编写单元测试。我有典型的MVC类:ObjectSchemaController,ObjectSchemaService和ObjectSchemaDao。我用@WebMvcTest编写了单元测试,用@MockBean模拟了我的服务和dao类。 (按照本指南:https://www.baeldung.com/spring-boot-testing

以下是我的单元测试:

@RunWith(SpringRunner.class)
@WebMvcTest(ObjectSchemaController.class)
public class ObjectSchemaControllerTest2 {
    @Autowired
    private MockMvc mvc;
    @MockBean
    private ObjectSchemaService service;
    @MockBean
    private ObjectSchemaDao dao;
    @Autowired
    ObjectMapper objectMapper;
    @Test
    public void testCreateObjectSchemaPass() throws Exception {
        String payload = "{\"some_key\":\"some val\"}";
        ObjectSchema objectSchema = objectMapper.readValue(payload, ObjectSchema.class);

        Mockito.when(service.createSchema(objectSchema))
        .thenReturn(objectSchema);
        Mockito.when(dao.createSchema(objectSchema)).thenReturn(objectSchema);

        mvc.perform(MockMvcRequestBuilders.post("/objectservice/schema/")
       .contentType("application/json")
       .content(objectMapper.writeValueAsString(objectSchema)))
       .andExpect(status().isOk());
    }

}

下面是我的服务类:

@Service
public class ObjectSchemaService {
    @Autowired
    ObjectSchemaDao objectSchemaDao;

    public ObjectSchema createSchema(@Valid ObjectSchema objectSchema)throws Exception {
        return objectSchemaDao.createSchema(objectSchema);
    }
}

单元测试面临的问题是,服务层没有执行并返回null值。

当我调试时,我可以看到执行到达我的控制器类和ObjectSchemaService在控制器中被模拟模拟。但是执行永远不会进入服务层,而service方法返回的值为null。

我引用了其他指南 - 他们正在做类似的步骤。但它不适合我。我在这里错过了什么?

我也看到这篇文章有类似的问题。

Unit Test POST with @WebMvcTest - @MockBean Service returns null

我确保输入对象到我的实际控制器和我在单元情况下传递的对象都是同一个类的实例。

unit-testing spring-boot mockito spring-boot-test mockmvc
2个回答
0
投票

你在嘲笑ObjectSchemaService但没有预期的行为。您需要为被模拟的服务设置行为。所以取决于方法签名和结果有些想法。

Mockito.when(service.createSchema(Mockito.any(ObjectSchema.class)).thenReturn(objectSchema);

目前,ObjectSchemaService mock只返回一个default value,在你的情况下为null。

为了透明和不引人注目,所有Mockito模拟默认返回'nice'值。例如:零,假,空集合或空值。

如果您使用ObjectSchemaService的详细信息更新您的答案,我也可以更新我的答案。


0
投票

您模拟了ObjectSchemaService,因此您需要告诉服务在调用方法时如何模拟服务中的值。如果你不嘲笑服务的价值Mockito不知道他们必须返回什么,总是给你null。在这个测试中不需要模拟ObjectSchemaDao。

注意:我在代码中使用Lombok作为ObjectSchema.builder()返回带有Id的对象,当存储在数据库中时,可以使用构造函数。假设服务返回对象。

代码如下所示:

import static org.mockito.BDDMockito.given;

@Test
public void testCreateObjectSchemaPass() throws Exception {
        String payload = "{\"some_key\":\"some val\"}";
        ObjectSchema objectSchema = objectMapper.readValue(payload, ObjectSchema.class);
        given(service.createSchema(objectSchema)).willReturn(
                ObjectSchema.builder()
                        .id(1)
                        .someKey("Some Val")
                        .build());
        mvc.perform(MockMvcRequestBuilders.post("/objectservice/schema/").contentType("application/json").content(objectMapper.writeValueAsString(objectSchema)))
                .andExpect(status().isOk());
    }
© www.soinside.com 2019 - 2024. All rights reserved.