使用@WebMvcTest的Spring Boot单元测试-执行不会从控制器进入服务层,并且返回null且没有错误

时间:2019-03-29 10:32:49

标签: unit-testing spring-boot mockito spring-boot-test mockmvc

我正在为我的Spring Boot应用程序的控制器编写单元测试。 我有典型的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);
    }
}

我在单元测试中面临的问题是,服务层无法执行并返回空值。

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

我参考了其他指南-他们正在执行类似的步骤。但是它对我不起作用。我在这里想念什么?

我也看到过类似问题的帖子。

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

我确保我的实际控制器和我要以单位为例传递的输入对象都是同一类的实例。

2 个答案:

答案 0 :(得分:0)

您正在嘲笑ObjectSchemaService,但是没有预期的行为。 您需要为被模拟的服务设置行为。因此,取决于方法签名和结果,就像这样。

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

目前,ObjectSchemaService模拟仅返回default value,在您的情况下为空。

  

为了透明且不干扰,默认情况下,所有Mockito模拟都返回“ nice”值。例如:零,假,空集合或空。

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

答案 1 :(得分: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());
    }