2013-06-03 8 views
7

Ho un @Aspect che tesse l'esecuzione di tutti i metodi di azione del mio controller. Funziona benissimo quando eseguo il sistema, ma non nel test delle unità(). Sto usando un Mockito JUnit nel modo folowing:Spring AOP Aspetto non funzionante con 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(); 
     }  
     ... 
    } 

con qualche @Test utilizzando mockMvc.perform().

E il mio aspetto sono:

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

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

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

Ho lo stesso problema. Ho notato che gli aspetti si attivano se si utilizza l'alternativa '' 'webAppContextSetup''' piuttosto che' '' standaloneSetup''', ma in tal caso i mock non vengono iniettati nel controller. Devo ancora capire come far funzionare entrambi –

risposta

0

Probabilmente si sta utilizzando Spring AOP, nel qual caso il chicco deve essere un bean Spring per AOP al lavoro, non autowiring nel controller è bypassando la primavera Meccanismo AOP totalmente.

Penso che la correzione deve essere di iniettare semplicemente nel controller

@Autowired 
@InjectMocks 
private UserController userController; 
+0

Guarda il codice di esempio. L'OP sta già facendo esattamente quello che hai suggerito. –

+0

Sì, mancava l'annotazione @Autowire nell'esempio, ora l'ho aggiunta in –

8

Ho avuto lo stesso problema e questo è quello che ho fatto.

In primo luogo è necessario utilizzare webAppContextSetup come suggerito Jason:

@Autowired 
private WebApplicationContext webApplicationContext; 

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

A questo punto l'aspetto dovrebbe essere attivato, ma Mockito non inietterà schernisce. Questo perché Spring AOP utilizza un oggetto proxy e i mock vengono iniettati su questo oggetto proxy anziché sull'oggetto proxy. Per risolvere questo problema è necessario scartare le ReflectionUtils oggetto e utilizzare invece di @InjectMocks annotazione:

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

A questo punto qualsiasi chiamata a quando (...) thenReturn (...) dovrebbe funzionare correttamente..

Viene spiegato qui: http://kim.saabye-pedersen.org/2012/12/mockito-and-spring-proxies.html

+2

Bello! Ho usato i generici per restituire un oggetto digitato ... cioè " T unwrapProxy (T bean)' –