2013-06-03 9 views
7

Mam @Aspect, który splata wykonanie wszystkich moich metod działania kontrolera. Działa to dobrze po uruchomieniu systemu, ale nie w testowaniu jednostkowym(). Używam Mockito się JUnit w folowing sposób:Aspekt wiosny AOP nie działa przy użyciu 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(); 
     }  
     ... 
    } 

niektóre @Test użyciu mockMvc.perform().

A moja Aspect są:

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

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

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

mam ten sam problem. Zauważyłem, że aspekty się uruchamiają, jeśli użyjesz alternatywnego '' 'webAppContextSetup''' zamiast' '' standaloneSetup''', ale w tym przypadku mocks nie zostaną wprowadzone do kontrolera. Muszę jeszcze dowiedzieć się, jak uzyskać oba działające –

Odpowiedz

0

Prawdopodobnie używasz wiosny AOP, w którym to przypadku fasola musi być sprężyną fasoli dla AOP do pracy, by nie autowiring w sterowniku jest ominięcie wiosnę Mechanizm AOP całkowicie.

myślę poprawka powinna być po prostu wstrzyknąć w kontrolerze

@Autowired 
@InjectMocks 
private UserController userController; 
+0

Zobacz przykład kodu. OP robi już dokładnie to, co zasugerowałeś. –

+0

Tak, brakowało adnotacji @Autowire w próbce, teraz dodałem ją w –

8

miałem ten sam problem i to, co mam zrobić.

Najpierw konieczne jest użycie webAppContextSetup jak Jason zasugerował:

@Autowired 
private WebApplicationContext webApplicationContext; 

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

W tym momencie aspekt powinien być wyzwalane ale Mockito nie wstrzyknie mocks. Dzieje się tak, ponieważ Spring AOP używa obiektu proxy, a mocks są wprowadzane do tego obiektu proxy zamiast do obiektu proxy. Aby rozwiązać ten problem należy rozpakować obiekt i wykorzystać ReflectionUtils zamiast @InjectMocks adnotacji:

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

W tym momencie każde wezwanie do kiedy (...) thenReturn (...) powinien działać prawidłowo..

To jest wyjaśnione tutaj: http://kim.saabye-pedersen.org/2012/12/mockito-and-spring-proxies.html

+2

Nice! Użyłem generics, aby zwrócić typowany obiekt ... ie ' T unwrapProxy (T bean)' –

Powiązane problemy