Spring启动-控制器测试失败,出现404代码

irlmq6kh  于 2022-10-30  发布在  Spring
关注(0)|答案(9)|浏览(196)

我想写一个测试控制器。下面是测试片段:

@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());
    }
}

控制器代码片段:

@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);
    }

模拟配置类:

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

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

    @Bean
    @Primary
    public WeatherStationService weatherServiceMock() {
        WeatherStationService mock = Mockito.mock(WeatherStationService.class);
        return mock;
    }

以下是错误堆栈跟踪:

java.lang.AssertionError: Status 
Expected :200
Actual   :404

我能理解这里的问题。

如何修复控制器的测试?

xdnvmnnf

xdnvmnnf1#

HTTP code 404,意味着没有找到资源(在服务器上)为您的请求,我认为您的控制器是不可见的(让我说是没有扫描)由Spring Boot .
一个简单的解决方案是扫描MockConfig类中的父包,这样Spring就可以拾取所有bean,

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

如果您不喜欢这种方法,您可以在basePackages中添加控制器的软件包名称

@ComponentScan(basePackages = {"edu.lelyak.controller","edu.lelyak.repository")

顺便说一句,你不必在MockConfig类中手动设置WeatherStationService,Spring boot可以为你注入一个mock,并在每个测试方法后自动重置它,你只需在你的测试类中声明它:

@MockBean
private IStationRepository stationRepository;

另一方面,在测试方法中调用get("/stations")之前,您应该模拟weatherService.getAllStations()(因为您没有运行integration test),这样您就可以:

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

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

xqk2d5yq

xqk2d5yq2#

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

brvekthn

brvekthn3#

我不知道为什么你的测试不起作用。但我有另一个解决方案对我有效。

@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());
    }
}
uplii1fm

uplii1fm4#

经过一些调试后,目标控制器似乎只是没有注册为方法处理程序。Spring扫描bean,看是否存在RestController注解。
但问题是,只有通过CGLIB代理bean时才能找到注解,但对于使用WebMvcTest的情况,它是通过JDK代理的。
因此,我搜索了负责做出选择的配置,最终找到了AopAutoConfiguration。因此,当使用SpringBootTest时,当您需要在控制器中使用WebMvcTest+PreAuthorize时,此配置会自动加载,然后只需用途:

@Import(AopAutoConfiguration.class)
lyr7nygr

lyr7nygr5#

我通过@ContextConfiguration(classes = MyConfig.class)导入外部配置类
当我将MyConfig注解@Configuration更改为@TestConfiguration时,它开始正常工作。

tag5nh1u

tag5nh1u6#

我找不到一个好的答案,但我能找到其中的一个原因。
我在测试中使用的是RestController上的@PreAuthorize
您可以在使用SpringBootTest的集成测试上使用this tip模拟Oauth。对于SpringBootTest,这也非常有效,但是使用SpringBootTest,您会加载许多其他资源(如JPA),这些资源对于执行简单的Controller测试是不必要的。
但是对于@WebMvcTest,这并不像预期的那样工作。使用WithMockOAuth2Scope注解足以阻止来自身份验证问题的401错误,但是在那之后WebMvcTest找不到其余的端点,返回404错误代码。
移除控制器上的@PreAuthorize后,WebMvcTest的测试通过。

eblbsuwk

eblbsuwk7#

基于accepted answer,在我的例子中,我已经根据另一个测试复制和修改了文件,但是忘记了更改类顶部的控制器的名称,这就是为什么它没有找到资源的原因,正如错误所说的那样。

@RunWith(SpringRunner.class)
@WebMvcTest(AnswerCommandController.class)
public class AnswerCommandControllerTest {
avwztpqn

avwztpqn8#

下面是一种不同的控制器测试方法,它对我很有效。
假设:类WeatherStationService@SpringBootApplication
然后,下面的测试类应该对您有效:

@RunWith(SpringRunner.class)
@SpringApplicationConfiguration(WeatherStationService.class)
@WebIntegrationTest
public class WeatherStationControllerTest {

    @Autowired
    private WebApplicationContext context;

    MockMvc mockMvc;

    @Before
    public void setup() {
        mockMvc =  MockMvcBuilders.webAppContextSetup(this.context).build();
    }

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

使用此测试设置,您应该不再需要MockConfig类。

u7up0aaq

u7up0aaq9#

在我的例子中,它是关于一个缺少的开始斜杠/
我已将/作为第一个字符附加到RequestMapping valueMockHttpServletRequestBuilder post urlTemplate参数。

相关问题