Spring Boot 测试方法调用未命中Sping Boot 中的服务

3bygqnnd  于 2023-03-08  发布在  Spring
关注(0)|答案(2)|浏览(211)

我正在尝试测试一个使用MapStruct的服务方法,如下所示:

@SpringBootTest(classes = {CategoryController.class, CategoryService.class, CategoryResponseMapperImpl.class})
class CategoryControllerTest {

    @Autowired
    private CategoryController categoryController;

    @MockBean
    private CategoryRepository categoryRepository;

    @MockBean
    private CategoryService categoryService;

    @Spy
    // @SpyBean
    public CategoryResponseMapper categoryResponseMapper = new CategoryResponseMapperImpl();

    @Test
    void test_findById() throws Exception {
        LocalDateTime dateTime = LocalDate.of(2022, 1, 1).atStartOfDay();

        Category category = new Category();
        category.setId(123L);
        category.setName("Category");
        category.setOrdinal(1);

        when(clock.instant()).thenReturn(dateTime.atZone(ZoneId.of("UTC")).toInstant());
        when(categoryRepository.findById(any())).thenReturn(Optional.of(category));

        MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/api/v1/categories/{id}", 123L);
        MockMvcBuilders.standaloneSetup(categoryController)
                .build()
                .perform(requestBuilder)
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.content().contentType("application/json"))
                .andExpect(MockMvcResultMatchers.content()
                        .string(
                                "{\"timestamp\":1640995200000,\"message\":\"Success\",\"data\":{\"id\":123,\"name\":\"Category\",\"ordinal\":1}}"));
    }
}
@GetMapping("/categories/{id}")
public ResponseEntity<ApiResponse<CategoryResponse>> findById(@PathVariable long id) {
    final CategoryResponse response = categoryService.findById(id);
    return ResponseEntity.ok(new ApiResponse<>(Instant.now(clock).toEpochMilli(), SUCCESS, response));
}

尽管测试命中了上面的控制器,但它没有命中下面的服务方法,响应数据返回为null:

private final CategoryRepository categoryRepository;
private final CategoryRequestMapper categoryRequestMapper;
private final CategoryResponseMapper categoryResponseMapper;

public CategoryResponse findById(Long id) {
    return categoryRepository.findById(id)
            .map(categoryResponseMapper::toDto)
            .orElseThrow(() -> {
                return new NoSuchElementFoundException(NOT_FOUND);
            });
}

那么,问题在哪里呢?

hts6caw3

hts6caw31#

尽管测试命中了上面的控制器,但它没有命中下面的服务方法
您的测试当前是为测试控制器而不是服务而编写的。因为categoryService被模拟。请考虑重写它。例如:

@Autowired
private CategoryService categoryService;

@MockBean
private CategoryRepository categoryRepository;

另一方面,如果你的目标是测试控制器,你将需要添加更多的模拟答案,如下所示:

when(categoryService.findById(any())).thenReturn(categoryResponse);
busg9geu

busg9geu2#

请尝试以下测试:

@AutoConfigureMockMvc
@SpringBootTest
class CategoryControllerTest {

    @MockBean
    private CategoryService categoryService;

    @Autowired
    private MockMvc mockMvc;

    @Test
    void test_findById() throws Exception {
        // Arrange
        LocalDateTime dateTime = LocalDate.of(2022, 1, 1).atStartOfDay();

        final long categoryId = 123L;
        Category category = new Category();
        category.setId(categoryId);
        category.setName("Category");
        category.setOrdinal(1);

        when(clock.instant()).thenReturn(dateTime.atZone(ZoneId.of("UTC")).toInstant());
        when(categoryService.findById(categoryId)).thenReturn(Optional.of(category));

        // Act & assert
        mockMvc.perform(get("/api/v1/categories/{id}", categoryId))
                .andExpect(status().isOk())
                .andExpect(content().contentType("application/json"))
                .andExpect(content().string("{\"timestamp\":1640995200000,\"message\":\"Success\",\"data\":{\"id\":123,\"name\":\"Category\",\"ordinal\":1}}"));
    }

}

通过这种设置,Spring基本上可以创建标准的应用程序上下文,@AutoConfigureMockMvc注解允许使用MockMvc对象向控制器发出请求。

相关问题