本文介绍了Spring AOP 方面无法使用 Mockito的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an @Aspect that weaves the execution of all my controller action methods. It works fine when I run the system, but not in unit testing. I'm using Mockito and junit in the following way:

@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() 使用一些 @Test.

我的方面是:

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

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

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

推荐答案

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

First it is necessary to use webAppContextSetup as Jason suggested:

@Autowired
private WebApplicationContext webApplicationContext;

@Before
public void setUp() throws Exception {
   ...
   mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}

此时应该触发方面,但 Mockito 不会注入模拟.这是因为 Spring AOP 使用代理对象,并且模拟被注入到这个代理对象而不是代理对象.要解决这个问题,有必要解开对象并使用 ReflectionUtils 而不是 @InjectMocks 注释:

At this point the aspect should be triggered but Mockito will not inject mocks. This is because Spring AOP uses a proxy object and the mocks are being injected to this proxy object instead of the proxied object. To fix this it is necessary to unwrap the object and use ReflectionUtils instead of @InjectMocks annotation:

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(...) 的调用都应该正常工作.

At this point any call to when(...).thenReturn(...) should work properly.

这里有解释:http://kim.saabye-pedersen.org/2012/12/mockito-and-spring-proxies.html

这篇关于Spring AOP 方面无法使用 Mockito的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-20 05:26