Frühlings-Aspekt nicht ausgelöst, im unit-test
OK, wir reden Feder (3.2.0) MVC
Wir haben ein pointcut definiert, die ausgelöst werden, "um" eine Anmerkung in etwa so:
@Around("@annotation(MyAnnotation)")
public void someFunction() {
}
Dann in einem controller haben wir:
@Controller
@Component
@RequestMapping("/somepath")
public class MyController {
@Autowired
private MyService service;
...
@MyAnnotation
@RequestMapping(value = "/myendpoint", method = RequestMethod.POST, produces = "application/json")
@ResponseBody
public Object myEndpoint(@RequestBody MyRequestObject requestObject, HttpServletRequest request, HttpServletResponse response) {
...
return service.doSomething(requestObject);
}
}
Dann haben wir einen unit test, der wie folgt aussieht:
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"../path/to/applicationContext.xml"})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class})
public class MyControllerTest {
private MockMvc mockMvc;
@InjectMocks
private MyController controller;
@Mock
private MyService myService;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
@Test
public void myTest() {
MyRequest request = new MyRequest();
MyResponse response = new MyResponse();
String expectedValue = "foobar";
Mockito.when(myService.doSomething((MyRequest) Mockito.any())).thenReturn(response);
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post("/myendpoint");
String request = IOUtils.toString(context.getResource("classpath:/request.json").getURI());
builder.content(request);
builder.contentType(MediaType.APPLICATION_JSON);
mockMvc.perform(builder)
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.someKey").value(expectedValue));
Mockito.verify(myService, Mockito.times(1)).doSomething((MyRequest) Mockito.any());
}
}
Den test gut läuft, aber der Aspekt definiert, um die annotation (MyAnnotation) nicht ausgeführt. Diese führt nur in Ordnung, wenn der Endpunkt wird ausgelöst durch eine real Anfrage (z.B. beim laufen in einem servlet-container), aber eben nicht ausgelöst, wenn die Ausführung in der Prüfung.
Ist das ein besonders "feature" der MockMvc, dass es nicht trigger Aspekte?
FYI unsere applicationContext.xml konfiguriert ist, mit:
<aop:aspectj-autoproxy/>
und wie erwähnt die Aspekte tatsächlich funktionieren in der Realität einfach nicht in den test.
Jemand wissen, wie man diese Aspekte, um das Feuer?
Dank!
- Update. Wenn ich auf die
webAppContextSetup
ausstandaloneSetup
Anmerkungen ausgelöst WERDEN, aber offensichtlich in diesem Fall wird der controller aufgerufen wird, ist aber nicht das, das die verhöhnt injiziert, so führt er Sie mit echter service-Klassen. Also entweder das problem löst Anmerkungen mitstandaloneSetup
oder Einspritzen von mocks mitwebAppContextSetup
- Weiteres update. Es scheint, dass auch die manuelle Einstellung der Felder der controller im test schlägt fehl, auch. So etwas wie dieses:
MyController controller = wac.getBean(MyController.class);
Gibt eine andere Instanz als die, die verwendet wird, wenn die Anforderung verarbeitet wird. Ich sehe den Konstruktor fürMyController
wird zweimal aufgerufen
Du musst angemeldet sein, um einen Kommentar abzugeben.
OK.. also die Lösung schließlich präsentierte sich vom.. Ihr ahnt es.. Lesen Sie in der Dokumentation :/
http://docs.spring.io/spring-framework/docs/3.2.0.BUILD-SNAPSHOT/reference/htmlsingle/#spring-mvc-test-framework
Also die endgültige Lösung sieht wie folgt aus:
Dann kann man einfach definieren Sie eine Kontext-Datei für diesen test
testContext.xml
hat, dass der mock von der service-Objekt:Allem die MyService Instanz ist
@Autowired
in den test, so kann es orchestriert werden.Dies ermöglicht Ihnen, mock aus alle Instanzen, die Sie mögen, ob Sie in service-Klassen, Aspekte etc, solange Sie den Namen der bean entsprechend. Also in diesem Fall die
MyService
würde deklariert werden als: