Spring Boot-控制器测试失败并显示404代码

naz*_*art 4 spring unit-testing controller spring-boot

我想为控制器编写测试。这是测试代码段:

@RunWith(SpringRunner.class)
@WebMvcTest(WeatherStationController.class)
@ContextConfiguration(classes = MockConfig.class)
public class WeatherStationControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private IStationRepository stationRepository;

    @Test
    public void shouldReturnCorrectStation() throws Exception {

        mockMvc.perform(get("/stations")
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk());
    }
}
Run Code Online (Sandbox Code Playgroud)

控制器代码段:

@RestController
@RequestMapping(value = "stations")
public class WeatherStationController {

    @Autowired
    private WeatherStationService weatherService;

    @RequestMapping(method = RequestMethod.GET)
    public List<WeatherStation> getAllWeatherStations() {
        return weatherService.getAllStations();
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public WeatherStation getWeatherStation(@PathVariable String id) {
        return weatherService.getStation(id);
    }
Run Code Online (Sandbox Code Playgroud)

MockConfig类:

@Configuration
@ComponentScan(basePackages = "edu.lelyak.repository")
public class MockConfig {

    //**************************** MOCK BEANS ******************************

    @Bean
    @Primary
    public WeatherStationService weatherServiceMock() {
        WeatherStationService mock = Mockito.mock(WeatherStationService.class);
        return mock;
    }
Run Code Online (Sandbox Code Playgroud)

这是错误堆栈跟踪:

java.lang.AssertionError: Status 
Expected :200
Actual   :404
Run Code Online (Sandbox Code Playgroud)

我可以在这里找到问题所在。
如何修复控制器测试?

小智 10

经过一些调试后,目标控制器似乎根本没有注册为方法处理程序。Spring 扫描 bean 是否存在RestController注释。

但问题是,只有当 bean 通过CGLIB代理时才能找到注释,但对于我们使用WebMvcTest它由JDK代理的情况。

结果我就去寻找负责做出选择的配置,终于找到了AopAutoConfiguration。因此,当使用 SpringBootTest 时,当您WebMvcTest+PreAuthorize在控制器中需要时,会自动加载这个测试,然后只需使用:

@Import(AopAutoConfiguration.class)
Run Code Online (Sandbox Code Playgroud)


O.B*_*adr 9

HTTP代码404,意味着未找到用于您请求的资源(在服务器上),我认为您的控制器在春季启动时是不可见的(让我说未被扫描)。

一种简单的解决方案是扫描MockConfig类中的父包,以便spring可以拾取所有bean,

@ComponentScan(basePackages = "edu.lelyak") // assuming that's the parent package in your project
Run Code Online (Sandbox Code Playgroud)

如果您不喜欢这种方法,则可以在以下位置添加控制器的程序包名称 basePackages

@ComponentScan(basePackages = {"edu.lelyak.controller","edu.lelyak.repository") 
Run Code Online (Sandbox Code Playgroud)

顺便说一句,您不必WeatherStationServiceMockConfig类中手动设置,Spring boot可以为您注入一个模拟并在每个测试方法后自动将其重置,您只需在测试类中声明它即可:

@MockBean
private IStationRepository stationRepository;
Run Code Online (Sandbox Code Playgroud)

另一方面,您应该weatherService.getAllStations()在调用get("/stations")测试方法之前进行模拟(因为您没有运行Integration test),因此您可以执行以下操作:

List<WeatherStation> myList = ...;
//Add element(s) to your list
 Mockito.when(stationService.getAllStations()).thenReturn(myList);
Run Code Online (Sandbox Code Playgroud)

您可以在以下位置找到更多信息:

  • 对我来说,结果就像在请求路径开头缺少“ /”一样简单。我在控制器测试中尝试使用“ v1 / user / {id}”而不是“ / v1 / user / {id}”。 (2认同)

rou*_*gou 7

我遇到过同样的问题。尽管使用@WebMvcTest(MyController.class). 这意味着它的所有映射都被忽略,导致 404。添加@Import(MyController.class)解决了问题,但当我已经指定要测试的控制器时,我没想到导入是必要的。

  • 这没有任何意义,但对我有用:D。我正在使用 Spring 启动 2.4.4 (5认同)

Pat*_*ick 6

我不确定为什么您的测试无法正常进行。但是我有另一个适合我的解决方案。

@SpringBootTest
public class ControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.standaloneSetup(new TestController()).build();
    }

    @Test
    public void shouldReturnCorrectStation() throws Exception {
        mockMvc.perform(get("/stations")
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk());
    }
}
Run Code Online (Sandbox Code Playgroud)