레알윙 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);
    }

}
반응형