2016-04-20 89 views
2

我有一個Spring MVC的應用程序,我用一個方面捕獲異常所有控制器方法如何在Spring MVC應用程序

@Component 
@Aspect 
public class ControllerExceptionAspect { 

    private Logger logger; 

    public ControllerExceptionAspect() { 
     logger = Logger.getLogger(ControllerExceptionAspect.class); 
    } 

    public ControllerExceptionAspect(Logger logger) { 
     this.logger = logger; 
    } 

    // Catching all exceptions from all methods in all controllers classes 

    @AfterThrowing(pointcut = "execution(* com.my.package..controller..*(..))", throwing = "exception") 
    public void afterThrowingAdvice(Exception exception) { 
     logger.error("CONTROLLER ASPECT: EXCEPTION IN METHOD -> " +  
     exception.getClass()); 
    } 
} 

看點工作正常,但可惜的是,我不能測試它測試看點。我試過很多次,但不能得到如何捕捉一方面方法中是否叫我模擬控制器異常後

@SuppressWarnings("ALL") 
@RunWith(SpringJUnit4ClassRunner.class) 
@WebAppConfiguration 
@ContextHierarchy({ 
     @ContextConfiguration(classes = RootConfig.class), 
     @ContextConfiguration(classes = WebConfig.class) 
}) 
public class ControllerExceptionAspectTest { 

    @Autowired 
    ApplicationContext applicationContext; 

    @Test 
    public void testControllerExceptionAspectGetsExecutedWhenExceptionOccures(){ 
     HomeController homeController = (HomeController)applicationContext.getAutowireCapableBeanFactory().getBean("homeController"); 
     try{homeController.callMethod("00000");} 
     catch (Exception e){} 
     ControllerExceptionAspect controllerExceptionAspect = (ControllerExceptionAspect)applicationContext.getAutowireCapableBeanFactory().getBean("controllerExceptionAspect"); 
     // HOW TO CATCH THAT ASPECT METHOD WAS CALLED??? 
    } 
} 
+0

作爲[Spring文檔(http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-pointcuts-designators)說,如果你將使用完整的AspectJ而不是Spring AOP,你可以在你的測試中使用像'adviceexecution()'這樣的切入點。 – kriegaex

回答

2

我認爲你想達到什麼目的是測試您所創建的配置(方面的切點),而不是可以單元測試的方面本身。我害怕的是沒有簡單的方法來實現這一點。

您可以在捕捉日誌或其他想法時遵循一些互聯網建議。老實說,只有在你確實需要測試它被調用時,我纔會測試Aspect的預期行爲。如果它正在登錄,我不會這樣做。如果它設置了某些東西(或其他副作用),我會驗證該值是否在數據庫中。這是集成測試的渺茫之地。

如果你真的,真的必須按照你想要的方式測試方面,你可以寫一些類似給定的代碼。但請記住,普通(非測試)運行時彈簧配置需要虛擬實現Spring上下文中存在的Verifier接口。

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(Config.class) 
public class AspectTesting { 

    @Autowired 
    ServiceWithAspect service; 

    @Autowired 
    Verifier verifyingAspect; 

    @Test 
    public void test() { 
     // given 
     boolean condition = false; 

     // when 
     try { 
      service.doit(); 
     } catch (Exception swallow) {} 

     // then 
     try { 
      condition = ((VerifyingAspect) ((Advised) verifyingAspect).getTargetSource().getTarget()).wasExecuted(); 
     } catch (Exception swallow) {} 

     // then 
     Assert.assertTrue(condition); 
    } 
} 

@Configuration 
@EnableAspectJAutoProxy 
@ComponentScan("aspects") 
class Config { 
} 

@Component 
class VerifyingAspect implements Verifier { 

    private boolean executed = false; 

    public boolean wasExecuted() { 
     return executed; 
    } 

    @Override 
    public void invoked() { 
     executed = true; 
    } 
} 

@Service 
class ServiceWithAspect { 
    public void doit() { 
     throw new RuntimeException(); 
    } 
} 

@Component 
@Aspect 
class TestedAspect { 

    @Autowired 
    Verifier verifier; 

    @AfterThrowing(pointcut = "execution(* *(..))", throwing = "exception") 
    public void afterThrowingAdvice(Exception exception) { 
     // your aspect logic here 
     verifier.invoked(); 
    } 
} 

interface Verifier { 
    void invoked(); 
}