web-dev-qa-db-fra.com

Résolution du port déjà utilisé dans un test de démarrage Spring PORT DÉFINI

J'ai une application de démarrage à ressort qui démarre et exécute une classe qui écoute événement Application Ready pour appeler un service externe pour récupérer des données et ensuite utiliser ces données pour en pousser règles au chemin de classe pour l'exécution. Pour les tests locaux, nous avons raillé le service externe au sein de notre application qui fonctionne très bien au démarrage de l'application.

L'annotation le problème est en cours de test en l'exécutant avec l'annotation Spring boot test et le conteneur de la jetée intégré sur:

  • PORT ALÉATOIRE
  • PORT DÉFINI

En cas de PORT ALÉATOIRE , au démarrage de l'application, il récupère l'URL du service simulé dans le fichier de propriétés sur un port défini et n'a aucune idée où le conteneur intégré est en cours d'exécution car il est récupéré de manière aléatoire, d'où l'échec de la réponse.

En cas de PORT DÉFINI , pour le premier fichier de cas de test, il s'exécute correctement, mais au moment où le fichier suivant est récupéré, il échoue en disant que le port est déjà utilisé.

Les cas de test sont partitionnés logiquement dans plusieurs fichiers et nécessitent que le service externe soit appelé avant que le conteneur ne commence à charger les règles.

Comment puis-je partager le conteneur intégré entre les fichiers de test en cas d'utilisation d'un port défini ou refactoriser mon code d'application à la place pour obtenir le port aléatoire lors du démarrage pendant l'exécution du scénario de test.

Toute aide serait appréciée.

Code de démarrage de l'application:

@Component
public class ApplicationStartup implements ApplicationListener<ApplicationReadyEvent> {

@Autowired
private SomeService someService;

@Override
public void onApplicationEvent(ApplicationReadyEvent arg0) {

    try {
        someService.callExternalServiceAndLoadData();
    }
    catch (Execption e) {}
    }
 }

Annotations du code de test: Test1

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource("classpath:test-application.properties")
public class Test1 {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void tc1() throws IOException {.....}

Annotations de code de test: Test2

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource("classpath:test-application.properties")
public class Test2 {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void tc1() throws IOException {.....}
13
ahj.ashish

J'ai rencontré le même problème. Je sais que cette question est un peu ancienne, mais cela peut être utile:

Les tests qui utilisent @SpringBootTest (webEnvironment = WebEnvironment.RANDOM_PORT) peuvent également injecter le port réel dans un champ à l'aide de l'annotation @LocalServerPort, comme illustré dans l'exemple suivant:

Source: https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-user-a-random-unassigned-http-port

L'exemple de code donné est:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class MyWebIntegrationTests {

    @Autowired
    ServletWebServerApplicationContext server;

    @LocalServerPort
    int port;

    // ...

}
3
cbreezier

Si vous insistez pour utiliser le même port sur plusieurs tests, vous pouvez empêcher Spring de mettre le contexte en cache pour d'autres tests en annotant votre classe de test avec: @DirtiesContext

Dans ton cas:

@RunWith(SpringRunner.class)
@DirtiesContext
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource("classpath:test-application.properties")

Voici une citation d'Andy Wilkinson de sa réponse sur cette discussion

Cela fonctionne comme prévu. Le framework de test de Spring Framework, par défaut, mettra en cache les contextes pour une éventuelle réutilisation par plusieurs classes de test. Vous avez deux tests avec une configuration différente (en raison de @TestPropertySource) afin qu'ils utilisent des contextes d'application différents. Le contexte du premier test sera mis en cache et maintenu ouvert pendant l'exécution du deuxième test. Les deux tests sont configurés pour utiliser le même port pour le connecteur de Tomcat. Par conséquent, lorsque le deuxième test est exécuté, le contexte ne démarre pas en raison d'un conflit de ports avec le connecteur du premier test. Vous avez quelques options:

  1. Utilisez RANDOM_PORT
  2. Supprimez @TestPropertySource de Test2 afin que les contextes aient une configuration identique et que le contexte du premier test puisse être réutilisé pour le deuxième test.
  3. Utilisez @DirtiesContext pour que le contexte ne soit pas mis en cache
2
Joel Neukom