백엔드/spring

Spring boot Junit5 Test mysql 연결 및 에러:Failed to load ApplicationContext for / Failed to replace DataSource with an embedded database for tests. 해결

DuckCow 2023. 3. 24. 16:48

spring boot 3.0.2 환경에서 웹페이지를 만들기위해 Junit5 테스트를 작성했다. 

 

@DisplayName("JPA 연결 테스트")
@Import(JpaRepositoryTest.TestJpaConfig.class)
@DataJpaTest
class JpaRepositoryTest {

    private final ArticleRepository articleRepository;
    private final ArticleCommentRepository articleCommentRepository;
    private final UserAccountRepository userAccountRepository;


    public JpaRepositoryTest(
            @Autowired ArticleRepository articleRepository,
            @Autowired ArticleCommentRepository articleCommentRepository,
            @Autowired UserAccountRepository userAccountRepository
    ) {
        this.articleRepository = articleRepository;
        this.articleCommentRepository = articleCommentRepository;
        this.userAccountRepository = userAccountRepository;
    }

    @DisplayName("select 테스트")
    @Test
    void givenTestData_whenSelecting_thenWorksFine() {
        // Given

        // When
        List<Article> articles = articleRepository.findAll();

        // Then
        assertThat(articles)
                .isNotNull()
                .hasSize(123);
    }

 

그런데, 실행 결과 다음과 같은 에러가 발생했다.

Failed to resolve parameter ~~

 

Failed to load ApplicationContext for ~~

 

Failed to replace DataSource with an embedded database for tests. ~~

 

 

왜 안될까 곱씹어 보다가 생각해보니, 마지막 에러를 보고  test와 datasource를 제대로 연결해주지 않았다는 생각이 들었다.

그런데 나는 @DataJpaTest 를 통해 datasource를 추가하지 않았나?  하고 생각해보니 내가 따로 embedded database를 추가하여 설정하지 않았다는 것을 깨달았다. 하지만, 내가 Test에서 원하는 것은 h2 embedded database가 아닌 실제 웹페이지 api 에서 사용하는 mysql database가 필요했고, 열심히 구글링하던 중 @AutoConfigureTestDatabase 을 사용하여 할 수 있다는 것을 알게 되었다.

 

https://kangwoojin.github.io/programing/auto-configure-test-database/.

@DisplayName("JPA 연결 테스트")
@Import(JpaRepositoryTest.TestJpaConfig.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)

class JpaRepositoryTest {
  • @DatabaseTest를 사용시 자동으로 Embedded db 를 사용하기 때문에 @AutoConfigureTestDatabase 를 사용해서 덮어버리는 것이다.
  • (replace = AutoConfigureTestDatabase.Replace.NONE)를 통해서 TestDatabaseAutoConfiguration에서 DataSource가 bean으로 등록되지 않게 하고 DataSourceAutoConfiguration에 의해서 DataSource가 등록되게 된다.
  • 이 때 property에 설정한 dataSource의 설정 값에 따라 적절한 DataSource를 생성하게 된다. SpringBoot 2.0 이상부터는 HikariDataSource가 Default로 등록이 되게 된다

 

HikariDataSource와 잘 연결되며 test가 정상적으로 잘 동작하는 것을 확인할 수 있다.
 
이때, 주의할 점은 application.yml의 ddl-auto: 설정을 create  로 해놓았다면 기존 db 가 drop  되고  테스트시 다 날라갈 수 있다.
jpa:
  database-platform: org.hibernate.dialect.MySQL8Dialect
  generate-ddl: true
  defer-datasource-initialization: true
  hibernate:
    ddl-auto: update
    show-sql: true #날리는 쿼리 보기
왜냐하면 진짜로 쿼리를 날려서 그 과정에서 기존의 것은 drop 되고 test 에서 Insert 한 것만 들어가기 때문이다.

그래서 나는 create로 했다가 다 날려서 update 로 바꾸고 다시 data 삽입했다.

 

"엥? @DataJpaTest 와 (h2) embedded database를 사용할땐 안 그랬는데, 왜죠?"
@DataJpaTest 와 @AutoConfigureTestDatabase 의 차이:
 
@DataJpaTest 는 기본적으로 rollback을 적용하기 때문이다.
"너 어처피 테스트하고 말 거니까 db는 그냥 냅두려고 rollback할게!"

 

그래서 insert 쿼리를 날리지 않고 영속성 컨텍스트에 가지고 있다가 flush 하지 않은 채로 rollback 하기 때문에 이러한 차이가 나는 것이다.