2 votes

Test unitaire de classes tissées par des aspects avec des beans Spring injectés en dépendance

Parce que le chargement tissé d'AspectJ LTW déclenché par Spring ne peut pas tisser les classes chargées avant l'initialisation de Spring, je suis en train de convertir un projet Spring en pur AspectJ LTW (avec l'agent java du tisseur AspectJ).

Cependant, cela active accessoirement l'AOP dans nos tests unitaires car je dois ajouter l'agent d'AspectJ au paramètre argLine du plugin Maven Surefire et à la configuration par défaut de TestNG dans l'IDE de mon équipe (IntelliJ IDEA).

Cela ne poserait pas de problème si nos Aspects ne dépendaient pas de Spring, mais certains d'entre eux ont en fait besoin que des beans Spring soient injectés dans leurs champs via la notation @Resource. Comme Spring n'est pas démarré pendant les tests unitaires, ces champs seront nuls et entraîneront des NullPointerException.

Même si je pourrais configurer deux exécutions indépendantes du plugin Surefire lors du processus de construction : une avec l'agent et l'autre sans; cette solution deviendrait impraticable car chaque développeur devrait toujours modifier la configuration des tests de l'IDE pour les tests unitaires par rapport aux autres tests qui nécessitent réellement l'AOP et le démarrage de Spring, pour chaque exécution de test indépendante (c'est-à-dire en dehors du processus de construction Maven).

Quelle serait la meilleure approche pour résoudre ce problème ? Existe-t-il un moyen de désactiver le chargement tissé d'AspectJ LTW tout en conservant la configuration de l'agent java intacte ? Ou peut-être une autre manière plus flexible de configurer le chargement tissé d'AspectJ qui n'ait pas les problèmes du chargement tissé d'AspectJ déclenché par Spring ?

3voto

kriegaex Points 6365

Nous pourrions débattre de savoir s'il est judicieux de rendre les aspects AspectJ purs dépendants de la magie de Spring ou s'il serait possible d'injecter des maquettes pour vos beans Spring dans les aspects. En réalité, un test unitaire n'est pas un test unitaire s'il nécessite un tel framework. Il en va vraisemblablement de même pour les aspects.

Quoi qu'il en soit, voici une solution bon marché : Utilisez des if() pointcuts pour tous les conseils pertinents et rendez-les dépendants de savoir si vous êtes en mode test ou non. Le surcoût en performances sera généralement minime, ne vous inquiétez pas. Essayez avant de dire que c'est trop cher.

Une autre possibilité, mais plus coûteuse, serait de déterminer si une classe de test se trouve dans le flux de contrôle du point de jonction actuellement intercepté via cflow() ou cflowbelow(). Je ne le recommande pas dans ce cas cependant.

Une troisième option pourrait consister à ajouter un autre META-INF/aop.xml au classpath en mode test, qui contient une instruction exclude globale excluant toutes les classes du tissage. La documentation d'AspectJ explique comment plusieurs aop.xml sont fusionnés de manière logique. Probablement, cette option est la meilleure car elle ne nécessite pas de modifier vos aspects. Je n'ai pas essayé, mais le ferais si vous rencontrez des difficultés et me le signalez.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X