ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [김영한 스프링] 07. 데이터 접근 기술(테스트) - 데이터베이스 연동 & 분리
    Spring/스프링 DB 2편 - 데이터 접근 활용 기술 2024. 1. 9. 12:44

    테스트 - 데이터베이스 연동

     

     

    데이터 접근 기술에 대해서 더 알아보기 전에 데이터베이스에 연동하는 테스트에 대해서 알아보자. 데이터 접근 기술은 실제 데이터베이스에 접근해서 데이터를 잘 저장하고 조회할 수 있는지 확인하는 것이 필요하다.

     

    지금부터 테스트를 실행할 때 실제 데이터베이스를 연동해서 진행해 보자.

    앞서 개발한 ItemRepositoryTest를 통해서 테스트를 진행할 것이다.

     

     

    main - application.properties

    spring.profiles.active=local
    spring.datasource.url=jdbc:h2:tcp://localhost/~/test
    spring.datasource.username=sa
    
    logging.level.org.springframework.jdbc=debug

     

     

    test - application.properties

    spring.profiles.active=test

     

    테스트 케이스는 src/test에 있기 때문에, 실행하면 src/test에 있는 application.properties 파일이 우선순위를 가지고 실행된다. 그런데 문제는 테스트용 설정에는 spring.datasource.url과 같은 데이터베이스연결 설정이 없다는 점이다.

     

    테스트 케이스에서도 데이터베이스에 접속할 수 있게 test의 application.properties를 다음과 같이 수정하자.

     

     

    test - application.properties 수정

    spring.profiles.active=test
    spring.datasource.url=jdbc:h2:tcp://localhost/~/test
    spring.datasource.username=sa
    
    logging.level.org.springframework.jdbc=debug

     

     

    테스트 실행 - 로컬DB

     

    @SpringBootTest

    @SpringBootTest
    class ItemRepositoryTest {}
    • ItemRepositoryTest는 @SpringBootTest를 사용한다. @SpringBootTest는 @SpringBootApplication를 찾아서 설정으로 사용한다

     

     

    @SpringBootApplication

    @Slf4j
    //@Import(MemoryConfig.class)
    //@Import(JdbcTemplateV1Config.class)
    //@Import(JdbcTemplateV2Config.class)
    @Import(JdbcTemplateV3Config.class)
    @SpringBootApplication(scanBasePackages = "hello.itemservice.web")
    public class ItemServiceApplication {}
    • @SpringBootApplication 설정이 과거에는 MemoryConfig.class를 사용하다가 이제는 JdbcTemplateV3Config.class를 사용하도록 변경되었다. 따라서 테스트도 JdbcTemplate을 통해 실제 데이터베이스를 호출하게 된다.
    • MemoryItemRepository -> JdbcTemplateItemRepositoryV3

     

     

    테스트 실행

    • updateitem() : 성공
    • save() : 성공
    • findItems() : 실패

     

     

    ItemRepositoryTest.findItems()

    @Test
    void findItems() {
        //given
        Item item1 = new Item("itemA-1", 10000, 10);
        Item item2 = new Item("itemA-2", 20000, 20);
        Item item3 = new Item("itemB-1", 30000, 30);
        
        itemRepository.save(item1);
        itemRepository.save(item2);
        itemRepository.save(item3);
        
        //여기서 3개 이상이 조회되는 문제가 발생
        test(null, null, item1, item2, item3);
    }

    결과적으로 테스트에서 저장한 3개의 데이터가 조회되어야 하는데, 기대보다 더 많은 데이터가 조회되었다.

     

     

    실패 원인

    문제는 H2 데이터베이스에 이미 과거에 서버를 실행하면서 저장했던 데이터가 보관되어 있기 때문이다. 이 데이터가 현재 테스트에 영향을 준다.

     

     

    테스트 - 데이터베이스 분리

     

     

    로컬에서 사용하는 애플리케이션 서버와 테스트에서 같은 데이터베이스를 사용하고 있으니 테스트에서 문제가 발생한다.

    이런 문제를 해결하려면 테스트를 다른 환경과 철저하게 분리해야 한다.

     

    가장 간단한 방법은 테스트 전용 데이터베이스를 별도로 운영하는 것이다.

    • H2 데이터베이스를 용도에 따라 2가지로 구분하면 된다.
      • jdbc:h2:tcp://localhost/~/test local에서 접근하는 서버 전용 데이터베이스
      • jdbc:h2:tcp://localhost/~/testcase test 케이스에서 사용하는 전용 데이터베이스

     

     

    데이터베이스 파일 생성 방법

    • 데이터베이스 서버를 종료하고 다시 실행한다.
      • 사용자명은 sa 입력
      • JDBC URL에 다음 입력, 
      • jdbc:h2:~/testcase (최초 한번)
      • ~/testcase.mv.db 파일 생성 확인
      • 이후부터는 jdbc:h2:tcp://localhost/~/testcase 이렇게 접속

     

     

    테이블 생성하기

    testcase 데이터베이스에도 item 테이블을 생성하자

    drop table if exists item CASCADE;
    create table item (
        id bigint generated by default as identity,
        item_name varchar(10),
        price integer,
        quantity integer,
        primary key (id)
    );

     

     

    접속 정보 변경

    이제 접속 정보를 변경하자 참고로 main에 있는 application.properties는 그대로 유지하고, test에 있는 application.properties만 변경해야 한다.

     

     

    test - application.properties

    spring.profiles.active=test
    spring.datasource.url=jdbc:h2:tcp://localhost/~/testcase
    spring.datasource.username=sa

    접속 정보가 jdbc:h2:tcp://localhost/~/test -> jdbc:h2:tcp://localhost/~/testcase로 변경된 것을 확인할 수 있다.

     

     

    실행

    • 처음에는 실행에 성공한다.
    • 그런데 같은 findItems() 테스트를 다시 실행하면 테스트에 실패한다.

    • 처음 테스트를 실행할 때 저장한 데이터가 계속 남아있기 때문에 두번째 테스트에 영향을 준 것이다.
    • 이 문제를 해결하려면 각각의 테스트가 끝날 때마다 해당 테스트에서 추가한 데이터를 삭제해야 한다. 그래야 다른 테스트에 영향을 주지 않는다.

     

    테스트에서 매우 중요한 원칙은 다음과 같다.

    • 테스트는 다른 테스트와 격리해야 한다.
    • 테스트는 반복해서 실행할 수 있어야 한다.

     

    물론 테스트가 끝날 때마다 추가한 데이터에 DELETE SQL을 사용해도 되겠지만, 이 방법도 궁극적인 해결책은 아니다. 만약 테스트 과정에서 데이터를 이미 추가했는데, 테스트가 실행되는 도중에 예외가 발생하거나 애플리케이션이 종료되어 버려서 테스트 종료 시점에 DELETE SQL을 호출하지 못할 수도 있다! 그러면 결국 데이터가 남아있게 된다.

     

    이런 문제를 어떻게 해결할 수 있을까?

     

     

    출처 :  https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-2/dashboard

     

    스프링 DB 2편 - 데이터 접근 활용 기술 강의 - 인프런

    백엔드 개발에 필요한 DB 데이터 접근 기술을 활용하고, 완성할 수 있습니다. 스프링 DB 접근 기술의 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., 백엔드 개발자

    www.inflearn.com

Designed by Tistory.