使用Mockito时Spring AOP方面不起作用

使用Mockito时Spring AOP方面不起作用,spring,junit,aop,mockito,Spring,Junit,Aop,Mockito,我有一个@Aspect,它编织了所有控制器动作方法的执行。当我运行系统时,它可以正常工作,但在单元测试中则不行。我以以下方式使用Mockito和junit: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("file:**/spring-context.xml") @WebAppConfiguration public class UserControllerTest { private Mock

我有一个
@Aspect
,它编织了所有控制器动作方法的执行。当我运行系统时,它可以正常工作,但在单元测试中则不行。我以以下方式使用Mockito和junit:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:**/spring-context.xml")
@WebAppConfiguration
public class UserControllerTest {        
    private MockMvc mockMvc;

    @Mock
    private RoleService roleService;

    @InjectMocks
    private UserController userController;

    @Before
    public void setUp() {
       MockitoAnnotations.initMocks(this);                    
       ...    
       mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
    }    
    ...
}
使用
mockMvc.perform()
进行一些
@测试

我的观点是:

@Pointcut("within(@org.springframework.stereotype.Controller *)")
public void controller() { }

@Pointcut("execution(* mypackage.controller.*Controller.*(..))")
public void methodPointcut() { }

@Around("controller() && methodPointcut()")
...

您可能正在使用SpringAOP,在这种情况下,bean必须是SpringBean,AOP才能工作,因为它没有在控制器中自动连接,而是完全绕过了SpringAOP机制

我认为解决方法应该是简单地注入控制器

 @Autowired
 @InjectMocks
 private UserController userController;

首先,有必要按照Jason的建议使用webAppContextSetup:

@Autowired
private WebApplicationContext webApplicationContext;

@Before
public void setUp() throws Exception {
   ...
   mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
此时应该触发方面,但Mockito不会注入mock。这是因为SpringAOP使用了一个代理对象,模拟被注入到这个代理对象而不是代理对象。要解决此问题,必须展开对象并使用ReflectionUtils而不是@InjectMocks注释:

private MockMvc mockMvc;

@Mock
private RoleService roleService;

private UserController userController;

@Autowired
private WebApplicationContext webApplicationContext;

@Before
public void setUp() {
   MockitoAnnotations.initMocks(this);                    
   UserController unwrappedController = (UserController) unwrapProxy(userController);
   ReflectionTestUtils.setField(unwrappedController, "roleService", roleService);   
   mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}

...

public static final Object unwrapProxy(Object bean) throws Exception {
/*
 * If the given object is a proxy, set the return value as the object
 * being proxied, otherwise return the given object.
 */
    if (AopUtils.isAopProxy(bean) && bean instanceof Advised) {
        Advised advised = (Advised) bean;
        bean = advised.getTargetSource().getTarget();
    }
    return bean;
}
此时,对when(…).thenReturn(…)的任何调用都应该正常工作


这里解释如下:

看看代码示例。OP已经完全按照您的建议进行了操作。是的,在示例中错过了@Autowire注释,我现在添加了它,因为我也有同样的问题。我注意到,如果使用备用
webAppContextSetup
而不是
standaloneSetup
,Aspect确实会触发,但在这种情况下,模拟不会注入控制器。我还没有弄明白如何让这两种方法都起作用。看,也不错!我使用泛型返回类型化对象。。。i、 e.
T展开(T bean)