web-dev-qa-db-fra.com

Recharger ou actualiser un contexte d'application Spring dans une méthode de test?

Je dois modifier les profils Spring actifs dans mon applicationContext dans une seule méthode de ma classe de test. Pour ce faire, je dois exécuter une ligne de code avant d'actualiser le concours, car j'utilise un ProfileResolver. J'ai essayé ce qui suit:

@WebAppConfiguration
@ContextConfiguration(locations = {"/web/WEB-INF/spring.xml"})
@ActiveProfiles(resolver = BaseActiveProfilesResolverTest.class)
public class ControllerTest extends AbstractTestNGSpringContextTests {
    @Test
    public void test() throws Exception {
        codeToSetActiveProfiles(...);
        ((ConfigurableApplicationContext)this.applicationContext).refresh();
        ... tests here ...
        codeToSetActiveProfiles(... back to prior profiles ...);
        ... ideally refresh/reload the context for future tests
    }
}

Mais je reçois:

Java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once

DirtiesContext ne fonctionne pas pour moi car il est exécuté APRÈS l'exécution de la classe/méthode, pas avant, et j'ai besoin d'exécuter une ligne de code avant de lancer l'actualisation/le rechargement.

Aucune suggestion? J'ai essayé de jeter un coup d'œil sur les écouteurs/crochets en cours d'exécution, mais je ne voyais pas d'emplacement évident pour m'insérer pour obtenir ce comportement.

10
David E

De par sa conception, l'actualisation par programme d'une ApplicationContext n'est pas explicitement prise en charge par Spring TestContext Framework. De plus, il n'est pas prévu qu'une méthode de test actualise un contexte.

Par conséquent, je vous recommanderais de réévaluer votre besoin d'actualisation et d'envisager des solutions de rechange, telles que le placement de méthodes de test nécessitant un ensemble différent de profils actifs dans une classe de test dédiée. 

En résumé, @ActiveProfiles prend en charge la configuration déclarative (via les attributs value et profiles) et la configuration programmatic (via l'attribut resolver) des profils actifs pour les tests, mais uniquement au niveau de la classe de test (pas à la méthode). niveau). Une autre option consiste à implémenter une ApplicationContextInitializer et à la configurer via @ContextConfiguration(initializers=...).

Le seul autre moyen d'affecter la ApplicationContextavant il est actualisé est d'implémenter une SmartContextLoader ou d'étendre l'une des classes fournies et de le configurer via @ContextConfiguration(loader=...). Par exemple, AbstractGenericContextLoader.customizeContext() permet de "personnaliser la GenericApplicationContext créée par le chargeur après que les définitions de bean ont été chargées dans le contexte mais que avant le contexte est actualisé".

Meilleures salutations,

Sam (auteur du Spring TestContext Framework)

12
Sam Brannen

Tous les contextes d'application ne prennent pas en charge plusieurs refresh. Selon javadoc pour AbstractRefreshableApplicationContext, seules les sous-classes de celui-ci ou de AbstractRefreshableWebApplicationContext acceptent refresh plus d'une fois ... et GenericApplicationContext dans aucune d'entre elles.

Vous devez utiliser une autre classe pour votre ApplicationContext afin de prendre en charge l'actualisation à chaud.

Modifier :

Lorsque vous utilisez l'annotation @ContextConfiguration, vous devez utiliser une implémentation ContextLoader ou SmartContextLoader personnalisée pour forcer spring à utiliser une ApplicationContext moins stupide. Mais je n'ai jamais trouvé un moyen propre et soigné d'y parvenir. Ainsi, lorsque j’ai besoin de XmlWebApplicationContext dans mes classes de test, je n’utilise pas @ContextConfiguration mais je crée et actualise mon contexte manuellement dans une méthode @Before ou au début d’un test.

Je reconnais que cela ne répond pas vraiment à votre question, mais vous pouvez le voir comme une solution de contournement.

0
Serge Ballesta