JUnit 을 이용한 테스트에서는 데이터 레이어를 테스트하는 경우가 있다. 이 경우 실제 DB 와 테스트용 DB 를 구분해야 하며, 테스트에서는 테스트용 DB 만 사용해야 한다.

@ActiveProfiles(“test”) 로 해결? 하지만 DB 가 모두 삭제된다.

스프링 부트를 이용하다 보면 JUnit 을 이용해 테스트 코드를 작성하는 경우가 많다.

테스트 중 integration test 를 하는 경우가 있는데 필자는 아래와 같이 DB 를 생성한 후 삭제한다.

DbDestinationTest

    @BeforeAll
    fun initialDataInput() = run {
        Repository1.saveAll(listOfEntities)
        Unit
    }

    @AfterAll
    fun clearData() = run {
        Repository1.deleteAll()
    }

테스트용 DB 와 실제 DB destination 이 모두 달라야 한다. 그렇지 않으면 clearData() 메서드가 모든 DB 데이터를 삭제한다.

그래서 필자는 DbDestinationTest 에서 @ActiveProfiles(“test”) 를 통해 테스트 설정 파일을 다르게 설정한 후 application-test.properties 파일을 만들어 db url 을 저장했다.

DbDestinationTest

@SpringBootTest
@ActiveProfiles("test")
@AutoConfigureDataMongo
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
internal class ServiceBleImplTest @Autowired constructor(
    private val repository1: Repository1
) {
        @BeforeAll
    fun initialDataInput() = run {
        repository1.saveAll(listOfEntities)
        Unit
    }

    @AfterAll
    fun clearData() = run {
        repository1.deleteAll()
    }
}

application-test.properties

# 로컬 docker container 에서 돌아가는 mongodb

datasource.mongo-connection-string=mongodb://localhost:27017/test?authSource\\\=admin&appname\\\=MongoDB%20Compass&ssl\\\=true

이렇게 하면 문제가 일반적으로는 해결된다.

하지만 필자의 케이스는 해결되지 않았다.

문제의 원인: 환경 변수 + Spring Boot 의 결함

이 글의 예제에서는 프로덕션용 application.properties 에서 아래와 같이 core property name 인 datasource.mongo-connection-string 에 변수를 한다. 왜냐하면, 데이터 소스 url 등 중요 정보를 코드에 남기지 않기 위해서이다. 그리고 해당 변수의 값은 서버의 환경 변수를 입력해 애플리케이션을 동작시킨다. 그렇게 application.properties 는 아래와 같은 형태이며, ${DATASOURCE_MONGO_CONNECTION_STRING} 에 환경 변수가 매핑된다.

application.properties

datasource.mongo-connection-string=${DATASOURCE_MONGO_CONNECTION_STRING}

문제는 변수명 DATASOURCE_MONGO_CONNECTION_STRING 가 core property name 인 datasource.mongo-connection-string 와 동일한 것이다. 우리가 보기엔 동일하지 않지만, 스프링 부트는 동일하게 인식한다. 그렇기 때문에 아래처럼 환경 변수를 설정하면 application-test.properties 에서의 모든 설정을 적용하되, datasource.mongo-connection-string 만 아래와 같이 mongomongo 로 설정한다.

환경 변수 설정(!= application.properties)

DATASOURCE_MONGO_CONNECTION_STRING=mongomongo

진짜 해결 방법

@TestPropertySource 를 이용해 직접 DB url 을 지정한다.

@TestPropertySource(properties = ["datasource.mongo-connection-string=mongodb://localhost:27017/test?authSource\\\\\\=admin&appname\\\\\\=MongoDB%20Compass&ssl\\\\\\=true"])
@SpringBootTest
@ActiveProfiles("test")
@AutoConfigureDataMongo
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
internal class ServiceBleImplTest @Autowired constructor(
    private val repository1: Repository1
) {
        @BeforeAll
    fun initialDataInput() = run {
        repository1.saveAll(listOfEntities)
        Unit
    }

    @AfterAll
    fun clearData() = run {
        repository1.deleteAll()
    }
}

위와 같이 하면 환경 변수명이 어떻든 @TestPropertySource 에서 지정한 DB 를 사용한다. 하지만 이 방법은 번거롭다. 되도록이면 application.properties 에서 변수명을 core property name 과 동일하게 설정하지 말자. 그러니까 아래와 같이 하자는 말이다.

application.properties

datasource.mongo-connection-string=${DATASOURCE_MONGO_CONNECTION_STRIN}

변수명에서 알파벳 G 만 제외해도 환경 변수가 core property name 인 datasource.mongo-connection-string 에 매핑되지 않는다.