2013-06-03 29 views
7

Tôi có @Aspect để thực hiện tất cả các phương thức hành động của bộ điều khiển của tôi. Nó hoạt động tốt whan tôi chạy hệ thống, nhưng không phải trong thử nghiệm đơn vị(). Tôi đang sử dụng Mockito một junit theo cách folowing:Spring AOP Aspect không hoạt động khi sử dụng Mockito

... 

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

với một số @Test using mockMvc.perform().

Và Aspect của tôi là:

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

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

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

Tôi có cùng một vấn đề. Tôi đã nhận thấy rằng các khía cạnh làm cháy nếu bạn sử dụng '' 'webAppContextSetup''' thay vì' '' standaloneSetup''' nhưng trong trường hợp đó các mocks không được tiêm vào bộ điều khiển. Tôi chưa biết làm thế nào để có được cả hai làm việc –

Trả lời

0

Bạn có lẽ sử dụng Spring AOP, trong trường hợp này đậu có phải là một đậu mùa xuân cho AOP để làm việc, bằng cách không autowiring trong bộ điều khiển nó được bỏ qua mùa xuân Cơ chế AOP hoàn toàn.

Tôi nghĩ việc sửa chữa nên chỉ đơn giản là tiêm trong bộ điều khiển

@Autowired 
@InjectMocks 
private UserController userController; 
+0

Nhìn vào mẫu mã. OP đã thực hiện chính xác những gì bạn đã đề xuất. –

+0

Đúng, đã bỏ lỡ chú thích @Autowire trong mẫu, tôi hiện đã thêm nó vào –

8

tôi đã cùng một vấn đề và đây là những gì tôi đã làm.

Đầu tiên nó là cần thiết để sử dụng webAppContextSetup như Jason gợi ý:

@Autowired 
private WebApplicationContext webApplicationContext; 

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

Tại thời điểm này các khía cạnh cần được kích hoạt nhưng Mockito sẽ không tiêm mocks. Điều này là do Spring AOP sử dụng một đối tượng proxy và các mocks đang được tiêm vào đối tượng proxy này thay vì đối tượng proxy. Để sửa lỗi này nó là cần thiết để unwrap các đối tượng và sử dụng ReflectionUtils thay vì @InjectMocks chú thích:

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

Tại thời điểm này bất kỳ cuộc gọi đến khi (...) thenReturn (...) nên làm việc đúng cách..

Điều này được giải thích tại đây: http://kim.saabye-pedersen.org/2012/12/mockito-and-spring-proxies.html

+2

Tốt đẹp! Tôi đã sử dụng Generics để trả về một đối tượng đã nhập ... tức là ' T unwrapProxy (T bean) ' –