2013-06-03 16 views
7

Ich habe eine @aspect, die die Ausführung aller meiner Controller Aktion Methoden webt. Es funktioniert gut, wenn ich das System laufen lasse, aber nicht im Komponententest(). Ich verwende Mockito einen JUnit in der folowing Weise:Spring AOP Aspekt funktioniert nicht mit 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(); 
     }  
     ... 
    } 

mit einigem @Test mockMvc.perform() verwenden.

Und mein Aspect ist:

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

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

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

Ich habe das gleiche Problem. Ich habe bemerkt, dass Aspekte feuern, wenn Sie das alternative '' 'webAppContextSetup''' anstelle von' '' standaloneSetup''' verwenden, aber in diesem Fall werden die Mocks nicht in den Controller injiziert. Ich muss noch herausfinden, wie Sie beide arbeiten –

Antwort

0

Sie verwenden wahrscheinlich Frühling AOP, wobei in diesem Fall die Bohne einen Spring-Bean sein muss für AOP, zu arbeiten, indem sie nicht in der Steuerung autowiring es die Feder unter Umgehung AOP Mechanismus total.

ich glaube, das Update sollte einfach sein, um in der Steuerung zu injizieren

@Autowired 
@InjectMocks 
private UserController userController; 
+0

Schauen Sie sich das Codebeispiel an. Das OP macht bereits genau das, was Sie vorgeschlagen haben. –

+0

Ja, habe die @Autowire Annotation in der Probe verpasst, ich habe sie jetzt in –

8

Ich hatte das gleiche Problem und das ist, was ich getan habe.

Zunächst ist es notwendig, webAppContextSetup zu verwenden, wie Jason vorgeschlagen:

@Autowired 
private WebApplicationContext webApplicationContext; 

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

An diesem Punkt der Aspekt ausgelöst werden soll, aber Mockito nicht verspottet injizieren. Dies liegt daran, dass Spring AOP ein Proxy-Objekt verwendet und die Mocks in dieses Proxy-Objekt anstelle des Proxy-Objekts injiziert werden. Um dies zu beheben ist es notwendig, die Aufgabe und Verwendung ReflectionUtils statt @InjectMocks Anmerkung auszupacken:

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

An dieser Stelle jeder Anruf, wenn (...) thenReturn (...) sollte ordnungsgemäß funktionieren..

Es wird hier erklärt: http://kim.saabye-pedersen.org/2012/12/mockito-and-spring-proxies.html

+2

hinzugefügt. Schön! Ich benutzte Generika, um ein getipptes Objekt zurückzugeben ... d. H. ' T unwrapProxy (T-Bean)' –