2016-04-20 3 views
2

У меня есть приложение Spring MVC, где я использую аспекты для перехвата исключений во всех методах контроллераКак проверить Aspect в приложении 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()); 
    } 
} 

Aspect отлично работает, но к сожалению, я не могу проверить это. Я много раз пытался, но не смог, как поймать, был ли называется метод Аспекта после того, как я моделировать исключение в контроллере

@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

Как [Спринг документация] (http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-pointcuts-designators) говорит, что если вы использовал бы полноценный AspectJ вместо Spring AOP, вы могли бы использовать pointcut, например 'advexecution()' в своем тесте. – kriegaex

ответ

2

Я думаю, что вы пытаетесь достичь тестируют конфигурацию, которые вы создали (аспекты Pointcut), а не сам аспект, который может быть проверен модулем. Я боюсь, что нет простого способа добиться этого.

Вы можете ознакомиться с некоторыми интернет-советами по ловлям журналов или другим идеям. Честно говоря, я проверил ожидаемое поведение Aspect, только если вам действительно нужно проверить, что он был вызван. Если это будет логин, я бы этого не сделал. Если он что-то устанавливает для db (или другого побочного эффекта), я бы проверил, находится ли значение в db. Это неплатежеспособность тестирования интеграции.

Если вы действительно должны проверить аспект так, как хотите, вы можете написать что-то подобное данному коду. Но помните, что для нормальной (не-тестовой) конфигурации Spring времени выполнения потребуется фиктивная реализация интерфейса Verifier, существующего в контексте Spring.

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