GithubHelp home page GithubHelp logo

Comments (3)

pbg0205 avatar pbg0205 commented on August 20, 2024

test container reference : https://www.testcontainers.org/

1. 테스트 컨테이너의 편리한 경우

  1. 데이터 엑세스 계층 통합 테스트
    • 운영과 동일한 상태로 개발 가능
    • 간단한 설정을 통한 컨테이너 생성 가능
  2. 애플리케이션 통합 테스트
    • 다양한 의존성 있는 컴포넌트(e.g. RDB, MQ) 를 편리하게 테스트해볼 수 있음
  3. UI/ 승인 테스트
    • 자동화된 UI 테스트 가능(Selenium 과 호환 가능?)

테스트 컨테이너의 단점

  • 테스트 수행 속도가 낮아진다.(컨테이너를 한번만 인스턴스화 하면 해결이 가능하다.)

JDBC 를 사용한다면 간단히 설정 가능

spring:
  datasource:
    url: jdbc:tc:mysql:8:///soolsul?TC_REUSABLE=true
    username: test
    password: test121212
    driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver

Redis의 경우, 별도로 만들어줘야 함.

public abstract class TestRedisContainer {

    private static final String DOCKER_REDIS_IMAGE = "redis:7.0.5-alpine";

    public static GenericContainer REDIS_CONTAINER =
            new GenericContainer<>(DockerImageName.parse(DOCKER_REDIS_IMAGE))
                    .withExposedPorts(6379)
                    .withReuse(true);

    static {
        REDIS_CONTAINER.start();

        System.setProperty("spring.redis.host", REDIS_CONTAINER.getHost());
        System.setProperty("spring.redis.port", REDIS_CONTAINER.getMappedPort(6379).toString());
    }
}

from be-tutorials.

pbg0205 avatar pbg0205 commented on August 20, 2024

https://www.testcontainers.org/quickstart/junit_5_quickstart/

JUnit 5 Quickstart

1. 테스트 컨테이너가 없을 떄의 문제점

local installation 환경의 문제점
image

  • local installation 에 의존한다.
  • 모든 개발자가 모두 같은 설치 버전으로 테스트를 한다는 보장이 없다. (같은 로컬 환경의 테스트가 필요하다)

1. Add Testcontainers as a test-scoped dependency

  • gradle 에서 아래와 의존성을 추가하면 JUnit5 와 통합된다. (통합된다는 의미가 뭐지...?)
testImplementation "org.junit.jupiter:junit-jupiter:5.8.1"
testImplementation "org.testcontainers:testcontainers:1.17.6"
testImplementation "org.testcontainers:junit-jupiter:1.17.6"

2. Get Testcontainers to run a Redis container during our tests

@Container
public GenericContainer redis = new GenericContainer(DockerImageName.parse("redis:5.0.3-alpine"))
    .withExposedPorts(6379);
  • @container (아직 뭔 소리인지 모르겠다.)
    • 테스트 생명 주기의 다양한 이벤트에 대해 해당 필드에 알리도록 JUnit 에게 지시한다.
    • 해당 객체는 Docker Hub에 특정 Redis 이미지를 사용하도록 구성하고 포트를 노출하도록 구성된 TestContainers GenericContainer 이다.

테스트 실행 시 TestContainer 는 아래와 같은 로그를 보여준다.

  • 테스트 메서드가 실행하기 이전 활성화 되었다는 메세지
  • local docker setup 을 확인하고 빠르게 테스트 한다는 메세지
  • 필요한 경우 image 를 pull 한다는 메세지
  • 새로운 컨테이너를 생성하고 준비하기까지 대기하는 상태
  • 테스트 이후 컨테이너를 종료 및 삭제하는 상태

3. Make sure our code can talk to the container

  • 테스트 컨테이너는 각가 컨테이너마다 랜덤한 포틀르 사용하지만 런타임 실제 포트도 편리하게 사용할 수 있다.
  • [notice] 웬만하면 getHost() 메서드를 사용하자. localhost의 경우 일부 환경에서만 동작하기 때문에 다른 환경에서 동작하지 않을 수 있음(e.g. CI 환경)
@Testcontainers
public class RedisBackedCacheIntTest {

    private RedisBackedCache underTest;

    // container {
    @Container
    public GenericContainer redis = new GenericContainer(DockerImageName.parse("redis:5.0.3-alpine"))
        .withExposedPorts(6379);

    // }

    @BeforeEach
    public void setUp() {
        String address = redis.getHost();
        Integer port = redis.getFirstMappedPort();

        // Now we have an address and port for Redis, no matter where it is running
        underTest = new RedisBackedCache(address, port);
    }

    @Test
    public void testSimplePutAndGet() {
        underTest.put("test", "example");

        String retrieved = underTest.get("test");
        assertThat(retrieved).isEqualTo("example");
    }
}

from be-tutorials.

pbg0205 avatar pbg0205 commented on August 20, 2024

사이드 리뷰 피드백

1. @DynamicPropertySource(참고 레퍼런스 : https://recordsoflife.tistory.com/607)

  • Spring ver. 5.2.5 이후부터 나온 어노테이션이며, 동적 값으로 속성(property)을 수정을 지원합니다.
  • Dynamic PropertyRegistry.add(String, Supplier) 메서드를 통해 Spring Enviorment 일부 속성을 추가합니다.
    @SpringBootTest
    @Testcontainers
    public class ArticleLiveTest {
    
        @Container
        static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:11")
          .withDatabaseName("prop")
          .withUsername("postgres")
          .withPassword("pass")
          .withExposedPorts(5432);
    
        @DynamicPropertySource
        static void registerPgProperties(DynamicPropertyRegistry registry) {
            registry.add("spring.datasource.url", 
              () -> String.format("jdbc:postgresql://localhost:%d/prop", postgres.getFirstMappedPort()));
            registry.add("spring.datasource.username", () -> "postgres");
            registry.add("spring.datasource.password", () -> "pass");
        }
        
        // tests are same as before
    }
    1. @DynamicPropertySource 어노테이션을 선언한 메서드는 정적으로 선언해야 합니다.
    2. 그리고 DynamicPropertyRegistry 유형 인수(Parameter) 하나만 허용해야 합니다.

    2. 대안 테스트 설비

    1. TestContainer, @DynamicPropertySource 모두 고정 장치 설정과 테스트 코드에 대한 의존도가 높아지는 단점이 있습니다.
    2. 인프라 설정 및 동적 구성 적용은 이를 필요로 하는 모든 테스트에서 복제됩니다.
    3. 이러한 단점을 피하기 위해 대부분의 테스트 프레임워크에서 제공하는 테스트 픽스처 기능을 사용할 수 있습니다.
      • Q. 테스트 픽스처?? 모든 테스트 전에 RDB 구성 + SpringBoot 구성, 테스트 이후 인스턴스 중지를 설정할 수 있습니다
      • 대표적인 예로는 BeforeAll, AfterAll 메서드가 있습니다. 그리고 이를 재사용하기 위해서 @ExtendsWith(---Extension.class) 를 사용하면 동일한 기능을 쉽게 재사용할 수 있습니다.

    3. 궁금증

    • @DynamicPropertySource 로 Spring Enviorment 설정하면 만약 재실행을 시작하지 않는 경우에는 메인 코드에는 영향을 미치지 않는 것일까? (어노테이션을 확인해보니 런타임 시점에 property 를 덮어씌우는 기능을 하는 것 같음.)

from be-tutorials.

Related Issues (13)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.