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();
}
테스트 성공