ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Testcontainers 기능
    백기선(인프런 강의)/더 자바, 애플리케이션을 테스트하는 다양한 방법 2020. 6. 7. 11:22
    반응형

    컨테이너 만들기

    • New GenericContainer(String imageName)
    @Container
    static GenericContainer postgreSQLContainer = new GenericContainer("postgres")
            .withExposedPorts(5432)
            .withEnv("POSTGRES_DB", "studytest");

     

    네트워크

    • withExposedPorts(int...)
      • DB port가 같다면 테스트 DB 및 운영서버 DB 중 랜덤하게 사용한다.(충돌하지 않는 포트 우선사용)
    ## 개발용 DB
    docker run -p 5432:5432 --name study-db -e POSTGRES_USER=study -e POSTGRES_PASSWORD=study -e POSTGRES_DB=study -d postgres
    
    ## 테스트용 DB
    docker run -p 15432:5432 --name study-testdb -e POSTGRES_USER=studytest -e POSTGRES_PASSWORD=studytest -e POSTGRES_DB=studytest -d postgres

     

    • getMappedPort(int)
      • 내 호스트가 어떤 포트를 사용했는지 확인
    @Container
    static GenericContainer postgreSQLContainer = new GenericContainer("postgres")
            .withExposedPorts(5432)
            .withEnv("POSTGRES_DB", "studytest");

     

    환경 변수 설정

    • withEnv(key, value)

     

    명령어 실행

    • withCommand(String cmd...)

     

    사용할 준비가 됐는지 확인하기

    • waitingFor(Wait)
      • 언제 서버가 가용되는데 시간이 걸리는지
    • Wait.forHttp(String url)
      • Http요청으로 응답을 확인 및 해당 컨테이너가 가용한지 확인 후 테스트 진행
    • Wait.forLogMessage(String message)
      • 특정한 로그 메세지가 출력이 되었는지  확인 후 테스트 진행
    @Container
    static GenericContainer postgreSQLContainer = new GenericContainer("postgres")
            .withExposedPorts(5432)
            .withEnv("POSTGRES_DB", "studytest")
            //.waitingFor(Wait.forListeningPort())
            //.waitingFor(Wait.forHttp("hello"))
            //.waitingFor(Wait.forLogMessage(regex, times))
            ;
    

     

    로그 살펴보기

    • getLogs()
      • 현재까지의 컨테이너의 로그들을 모두 가져오기
    • followOutput()
      • 스트리밍으로 로그를 출력
    @BeforeAll
    static void beforeAll() {
        Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(log);
        postgreSQLContainer.followOutput(logConsumer);
    }
    
    @BeforeEach
    void beforeEach() {
        System.out.println("===========");
        System.out.println(postgreSQLContainer.getMappedPort(5432));
        System.out.println(postgreSQLContainer.getLogs());
        studyRepository.deleteAll();
    }

     

     

     

    사용 예시

    import lombok.extern.slf4j.Slf4j;
    import me.whiteship.inflearnthejavatest.domain.Member;
    import me.whiteship.inflearnthejavatest.domain.Study;
    import me.whiteship.inflearnthejavatest.member.MemberService;
    import org.junit.After;
    import org.junit.jupiter.api.*;
    import org.junit.jupiter.api.extension.ExtendWith;
    import org.mockito.Mock;
    import org.mockito.junit.jupiter.MockitoExtension;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.ActiveProfiles;
    import org.springframework.test.context.TestPropertySource;
    import org.testcontainers.containers.GenericContainer;
    import org.testcontainers.containers.PostgreSQLContainer;
    import org.testcontainers.containers.output.Slf4jLogConsumer;
    import org.testcontainers.containers.wait.strategy.Wait;
    import org.testcontainers.junit.jupiter.Container;
    import org.testcontainers.junit.jupiter.Testcontainers;
    
    import java.util.Optional;
    
    import static org.junit.jupiter.api.Assertions.*;
    import static org.mockito.BDDMockito.given;
    import static org.mockito.BDDMockito.then;
    import static org.mockito.Mockito.times;
    
    @SpringBootTest
    @ExtendWith(MockitoExtension.class)
    @ActiveProfiles("test")
    @Testcontainers
    @Slf4j
    class StudyServiceTest {
    
        @Mock MemberService memberService;
    
        @Autowired StudyRepository studyRepository;
        
        static Logger log = LoggerFactory.getLogger(StudyServiceTest.class);
    
        /* @Container
        //아래와같이 DB이름 설정 가능
        static PostgreSQLContainer<?> postgreSQLContainer = new PostgreSQLContainer()
                .withDatabaseName("postgres");*/
        
        @Container
        static GenericContainer postgreSQLContainer = new GenericContainer("postgres")
                .withExposedPorts(5432)
                .withEnv("POSTGRES_DB", "studytest")
                //.waitingFor(Wait.forListeningPort())
                //.waitingFor(Wait.forHttp("hello"))
                //.waitingFor(Wait.forLogMessage(regex, times))
                		
                ;
        
        @BeforeAll
        static void beforeAll() {
            Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(log);
            postgreSQLContainer.followOutput(logConsumer);
        }
    
        @BeforeEach
        void beforeEach() {
            System.out.println("===========");
            System.out.println(postgreSQLContainer.getMappedPort(5432));
            System.out.println(postgreSQLContainer.getLogs());
            studyRepository.deleteAll();
        }
    
        @Test
        void createNewStudy() {
            // Given
            StudyService studyService = new StudyService(memberService, studyRepository);
            assertNotNull(studyService);
    
            Member member = new Member();
            member.setId(1L);
            member.setEmail("rlawls1991@email.com");
    
            Study study = new Study(10, "테스트");
    
            given(memberService.findById(1L)).willReturn(Optional.of(member));
    
            // When
            studyService.createNewStudy(1L, study);
    
            // Then
            assertEquals(1L, study.getOwnerId());
            then(memberService).should(times(1)).notify(study);
            then(memberService).shouldHaveNoMoreInteractions();
        }
    
        @DisplayName("다른 사용자가 볼 수 있도록 스터디를 공개한다.")
        @Test
        void openStudy() {
            // Given
            StudyService studyService = new StudyService(memberService, studyRepository);
            Study study = new Study(10, "더 자바, 테스트");
            assertNull(study.getOpenedDateTime());
    
            // When
            studyService.openStudy(study);
    
            // Then
            assertEquals(StudyStatus.OPENED, study.getStatus());
            assertNotNull(study.getOpenedDateTime());
            then(memberService).should().notify(study);
        }
    
    }
    반응형
Designed by Tistory.