testcontainer BeforeAllCallback 여러번 호출되는 문제

hyng·2023년 2월 1일
0

smilegate-winter-dev-camp

목록 보기
13/15

redis, mongoDB를 testcontainer로 띄우고 테스트를 진행했다.
docker에 컨테이너가 뜨는지 확인했더니 여러 개의 컨테이너가 실행되고 있었다.

컨테이너 setup메서드인 beforeAll()에 디버그를 찍어보니 메서드가 여러번 호출되고 있었다.

구글링을 해보니 테스트에서 @nested를 사용하였던 게 문제였다.

	@Nested
    @DisplayName("메시지가 100자를 넘는다면")
    class ContextWithMessageLengthOver100 {

      @Test
      @DisplayName("handleException을 호출한다")
      void ItCallsHandleException() throws InterruptedException {
        // given
        String topicId = "topicId";
        ChatMessage message = ChatMessage.of("user1", "s".repeat(101));

        // when
        session.send(String.format("/chat/%s/send", topicId), message);

        // then
        sleep(1000);
        verify(chatController).handleException(any(Exception.class));
      }
    }

https://github.com/micronaut-projects/micronaut-test/pull/404
https://stackoverflow.com/questions/60774567/beforeall-afterall-callbacks-of-junit5-extension-are-executed-for-each-nested

첫 번째 링크에서 나온 방법처럼 context를 확인하여 해결할 수도 있고 두번째 링크에서 나온 방법처럼 TestExecutionListener를 이용하여 해결할 수도 있다.
그중 첫 번째 방법으로 문제를 해결하였다.

@Override
  public void beforeAll(ExtensionContext context) {
    if (context.getTestClass().isPresent()) {
      Class<?> currentClass = context.getTestClass().get();
      if (isNestedClass(currentClass)) {
        return;
      }
    }
    System.out.println("Call beforeAll of extension");
    redis = new GenericContainer(DockerImageName.parse(REDIS_IMAGE))
      .withExposedPorts(REDIS_PORT);
    redis.start();
    System.setProperty("spring.data.redis.host", redis.getHost());
    System.setProperty("spring.data.redis.port", String.valueOf(redis.getMappedPort(REDIS_PORT
    )));

    mongoDB = new MongoDBContainer(DockerImageName.parse(MONGO_IMAGE))
      .withExposedPorts(MONGO_PORT);
      
    System.setProperty("spring.data.mongodb.host", mongoDB.getHost());
    System.setProperty("spring.data.mongodb.port", String.valueOf(mongoDB.getMappedPort(MONGO_PORT
    )));
  }

  private boolean isNestedClass(Class<?> currentClass) {
    return !ModifierSupport.isStatic(currentClass) && currentClass.isMemberClass();
  }

테스트 성공

profile
공부하고 알게 된 내용을 기록하는 블로그

0개의 댓글