Spring Boot - Test for controller fails with 404 code

后端 未结 8 1124
一个人的身影
一个人的身影 2021-01-04 18:17

I want to write a test for controller. Here is test snippet:

@RunWith(SpringRunner.class)
@WebMvcTest(WeatherStationController.class)
@ContextConfiguration(c         


        
相关标签:
8条回答
  • 2021-01-04 18:35

    In my case it was about a missing starting slash /

    I've appended / to both RequestMapping value and MockHttpServletRequestBuilder post urlTemplate parameters as first character.

    0 讨论(0)
  • 2021-01-04 18:38

    HTTP code 404, means no resource found (on the server) for your request, which I think that your controller is not visible(let me say is not scanned) by spring boot.

    A simple solution is scanning a parent package in MockConfig class, so spring can pick up all beans,

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

    if you don't like this approach, you can add the controller's package name in basePackages

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

    BTW, you don't have to manually set up WeatherStationService in MockConfig class, Spring boot can inject a mock for you and automatically reset it after each test method, you should just declare it in your test class:

    @MockBean
    private IStationRepository stationRepository;
    

    On the other hand, you should mock weatherService.getAllStations() before calling get("/stations") in your test method (as you're not running integration test), so you can do:

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

    You can find more in :

    • Testing improvements in Spring Boot 1.4

    • Spring Boot features: Testing

    0 讨论(0)
  • 2021-01-04 18:41

    Here is a different approach to the controller test that worked for me.

    Assumption: The class WeatherStationService is a @SpringBootApplication

    Then, the test class below should work for you:

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

    With this test setup, you should no longer need the MockConfig class.

    0 讨论(0)
  • 2021-01-04 18:52

    I am not sure why your test is not working. But I got another solution which works for me.

    @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());
        }
    }
    
    0 讨论(0)
  • 2021-01-04 18:53

    I had the same issue. The controller was not getting picked up despite specifying it with @WebMvcTest(MyController.class). This meant all of its mappings were ignored, causing the 404. Adding @Import(MyController.class) resolved the issue, but I didn't expect the import to be necessary when I'm already specifying which controller to test.

    0 讨论(0)
  • 2021-01-04 18:53

    I couldn't find a good answer but I could find one of the causes.

    I was using in my tests the @PreAuthorize on the RestController.
    You can mock the Oauth with this tip on the integration tests that use SpringBootTest. For SpringBootTest, this works very well too, but using SpringBootTest you load a lot of other resources (like JPA) that is not necessary to do a simple Controller test.

    But with @WebMvcTest this not works as expected. The use of the WithMockOAuth2Scope annotation can be enough to stop the 401 error from authentication problem, but after that the WebMvcTest can't find the rest endpoint, returning the 404 error code.

    After removing the @PreAuthorize on Controller, the test with WebMvcTest pass.

    0 讨论(0)
提交回复
热议问题