Spring 引导 JUnit 测试失败,预期状态为:<200> 但为:<404>

Spring Boot JUnit tests fail with Status expected:<200> but was:<404>

一段时间以来,我一直在努力为我的休息控制器进行 JUnit 测试。出于某种原因,每次我尝试 运行 它们时,我都会收到错误 Status expected:<200> but was:<404>。这是我的控制器:

@RestController
@RequestMapping("/travels")
@RequiredArgsConstructor
public class TravelController {

  private final TravelService travelService;

  private final TravelOutputDtoMapper travelOutputDtoMapper;

  @GetMapping
  public List<TravelOutputDto> getAll() {
    List<Travel> travels = travelService.getAll();

    return travels.stream()
            .map(travelOutputDtoMapper::travelToTravelOutputDto)
            .collect(Collectors.toList());
  }
}

这是我的测试:

@ExtendWith(SpringExtension.class)
@WebMvcTest(controllers = TravelController.class)
@ContextConfiguration(classes = {
    TravelOutputDtoMapper.class,
    TravelOutputDtoMapperImpl.class
})
class TravelControllerTest {

  @Autowired
  private MockMvc mockMvc;

  @MockBean
  private TravelService travelService;
  @Autowired
  private TravelOutputDtoMapper travelOutputDtoMapper;

  @Test
  void testGetAll() throws Exception {

      List<Travel> travels = mockTravelList();

      Mockito.when(travelService.getAll()).thenReturn(travels);


      mockMvc.perform(get("/travels"))
              .andExpect(status().isOk());
  }


  private List<Travel> mockTravelList() {
  // Dummy travel list
  }
}

我认为原因与 TravelOutputDtoMapper 有关,就好像我将它从控制器中删除并且不尝试注入它测试正在通过,但我找不到它为什么这样做的任何信息。自动装配的映射器有一个实例并且工作正常。

这是映射器:

@Mapper(componentModel = "spring")
public interface TravelOutputDtoMapper {

  @Mapping(target = "from", source = "entity.from.code")
  @Mapping(target = "to", source = "entity.to.code")
  TravelOutputDto travelToTravelOutputDto(Travel entity);
}

@ContextConfiguration 注释用于不同的目的:

@ContextConfiguration defines class-level metadata that is used to determine how to load and configure an ApplicationContext for integration tests.

使用 Spring 引导和 @WebMvcTest 无需手动指定如何加载上下文。这是在后台为您完成的。

如果你要使用这个注解,你会在这里指定你的主要 Spring 引导 class(你的入口点 class 带有 @SpringBootApplication 注解) .

从我在你的测试中看到的情况来看,你的问题是你想为 TravelOutputDtoMapper 提供一个实际的 bean,但模拟 TravelService.

在这种情况下,您可以使用 @TestConfiguration 向切片的 Spring TestContext 添加更多 bean:

// @ExtendWith(SpringExtension.class) can be removed. This extension is already registered with @WebMvcTest
@WebMvcTest(controllers = TravelController.class)
class TravelControllerTest {

  @Autowired
  private MockMvc mockMvc;

  @MockBean
  private TravelService travelService;

  @Autowired
  private TravelOutputDtoMapper travelOutputDtoMapper;


  @TestConfiguration
  static class TestConfig {
 
    @Bean
    public TravelOutputDtoMapper travelOutputDtoMapper() {
      return new TravelOutputDtoMapper(); // I assume your mapper has no collaborators 
    }
  }

  // ... your MockMvc tests
}