2017-11-07 2 views
3

HelloController.javaHat Frühling @GetMapping Arbeit mit MockMvc

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

Die Antwort, die ich hier 404 bekommen, und ich erwarte 200.

Aber es funktioniert und ich bekomme 200, wenn ich @GetMapping zu @RequestMapping (value = "{id}/hallo", Methode ändern = RequestMethod.GET)

Fehle ich hier etwas?

+0

Wie initialisierst du deine 'MockMvc'? –

+0

Ihr Code (und Grundannahmen) funktioniert gut für mich. Bitte poste ein [mcve]. –

+0

@SotiriosDelimanolis Ich habe die Testklasse jetzt aktualisiert.Ich habe nur nicht die Config-Datei enthalten – user3451476

Antwort

2

Ihre Konfiguration ist extrem nackte Knochen

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

Es registriert keine Spring MVC-Infrastruktur Bohnen, entweder implizit oder explizit.

Wenn MockMvc intern eine TestDispatcherServlet erstellt, um Ihre @Controller Klasse zu testen, muss sie auf einige Spring MVC-Infrastrukturtypen zurückgesetzt werden.

Unter diesen Typen ist Infrastruktur HandlerMapping welche

von Objekten implementiert werden, die eine Zuordnung zwischen den Anforderungen und handler Objekten definieren.

Die Implementierung Verzuges der TestDispatcherSerlet verwendeten DefaultAnnotationHandlerMapping (eine alte Klasse), die speziell für @RequestMapping aussieht, ist es nicht rekursiv einen Meta-Annotation-Lookup. Ihre @GetMapping annotierte Methode wird daher nicht gefunden und nicht als Handler registriert.

Wenn stattdessen Sie konfigurieren Ihr Anwendungskontext mit @EnableWebMvc

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

Frühling wird implizit ein RequestMappingHandlerMapping registrieren, die dieses „rekursiven“ Nachschlag für die Annotation Hierarchie macht (verschmelzenden genannt). Da @GetMapping mit @RequestMapping annotiert ist, wird die annotierte Handlermethode gefunden und registriert.


Was die @InjectMocks, beachten Sie, dass die Instanz durch das Feld verwiesen wird von dem unterscheidet verwendet, um die Anforderung durch das MockMvc Objekt ausgeführt zu handhaben. Die erste wird von Mockito, die zweite von Spring verwaltet.

+0

Bingo! das hat funktioniert. Vielen Dank! Wie für InjectMocks. Dieser Test, der die Controller-Methode direkt aufruft, sollte mit Mockmvc getestet werden und dann kann ich das Controller-Feld aus der Test-Klasse entfernen – user3451476

+0

Ihre Erklärung ist, im Ernst, ** unglaublich **. –

Verwandte Themen