简体   繁体   中英

Does spring @GetMapping work with MockMvc

HelloController.java

@RestController
class HelloController {

@GetMapping(value = "{id}/hello")
public ModelAndView listAPI(@PathVariable("id") String profileId) {
    ModelAndView mav = new ModelAndView();
    return mav;
 }    
}

HelloControllerTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = HelloConfigTest.class)
class HelloControllerTest {

@Inject
private WebApplicationContext webApplicationContext;

@Inject
private Foo mockFoo

@InjectMocks
HelloController helloController;

private MockMvc mockMvc;

    @Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
    mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}

@Test
public void testHello() throws Exception {
    mockMvc.perform(
        get("/{id}/campaigns", "id1"))
        .andExpect(status().isOk()));
  }  
}

    // I have another test that directly calls the controller method. 
// So I need @InjectMocks to get an instance of the controller

@Test
public void test2() {

    when(mockFoo.getX()).thenReturn(true);
    helloController.saveAPI();
}

HelloConfigTest.java

 @Configuration
 @ComponentScan("com.test.controller")
 class HelloConfigTest {

@Bean
public mockFoo() {
    return Mockito.mock(Foo.class); 
  }
}

The response that I get here is 404 and I expect 200.

But it works and I get 200 if I change @GetMapping to @RequestMapping (value="{id}/hello", method=RequestMethod.GET)

Am I missing anything here ?

Your configuration is extremely bare bones

@Configuration
@ComponentScan("com.test.controller")
class HelloConfigTest {

It doesn't register any Spring MVC infrastructure beans, either implicitly or explicitly.

When MockMvc , internally, creates a TestDispatcherServlet to test your @Controller class, it has to defer to some default Spring MVC infrastructure types.

Among these infrastructure types is HandlerMapping which is

to be implemented by objects that define a mapping between requests and handler objects.

The default implementation used by the TestDispatcherSerlet is DefaultAnnotationHandlerMapping (an old class) which looks for @RequestMapping specifically , it doesn't recursively do a meta-annotation lookup. Your @GetMapping annotated method is therefore not found and not registered as a handler.

If, instead, you configure your application context with @EnableWebMvc

@Configuration
@ComponentScan("com.test.controller")
@EnableWebMvc
class HelloConfigTest {

Spring will implicitly register a RequestMappingHandlerMapping , which does do this "recursive" lookup for the annotation hierarchy (called merging ). Since @GetMapping is annotated with @RequestMapping , the annotated handler method will be found and registered.


As for the @InjectMocks , note that the instance referenced by the field is different from the one used to handle the request performed by the MockMvc object. The former is managed by Mockito, the latter by Spring.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM