OK, we're talking Spring (3.2.0) MVC
We have an pointcut defined to be triggered "around" an annotation like so:
@Around("@annotation(MyAnnotation)")
public void someFunction() {
}
Then in a controller we have:
@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);
}
}
Then we have a unit test that looks like this:
@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());
}
}
The test runs fine, but the aspect defined around the annotation (MyAnnotation) does not execute. This executes just fine when the endpoint is triggered by a real request (e.g. when running in a servlet container) but just doesn't fire when running in the test.
Is this a particular "feature" of MockMvc that it doesn't trigger aspects?
FYI our applicationContext.xml is configured with:
<aop:aspectj-autoproxy/>
and as I mentioned the aspects do actually work in reality, just not in the test.
Anyone know how to get these aspects to fire?
Thanks!
webAppContextSetup
fromstandaloneSetup
the annotations ARE triggered, but obviously in that case the controller being called is not the one the the mocks injected so it executes with real service classes. So either the problem is triggering annotations withstandaloneSetup
, or injecting mocks withwebAppContextSetup
– InfractionMyController controller = wac.getBean(MyController.class);
Returns a different instance than the one used when the request is processed. I see the constructor forMyController
being called twice – Infraction