토이 프로젝트 스터디 #14
- 스터디 진행 날짜 : 6/28
 
- 스터디 작업 날짜 : 6/25 ~ 6/28
 
토이 프로젝트 진행 사항
AWS S3 로컬 테스트를 위해 LocalStack 적용 
내용
LocalStack
// build.gradle
testImplementation 'org.testcontainers:localstack:1.16.3'
build.gradle에 LocalStack 추가 
spring:
  main:
    allow-bean-definition-overriding: true
AWS 객체를 Mocking하기 위해 스프링 빈 오버라이딩 옵션 true로 설정 
@Profile("test")
@Configuration
public class LocalStackS3Config {
    DockerImageName localstackImage = DockerImageName.parse("localstack/localstack");
    @Bean(initMethod = "start", destroyMethod = "stop")
    public LocalStackContainer localStackContainer() {
        return new LocalStackContainer(localstackImage)
                .withServices(LocalStackContainer.Service.S3);
    }
    @Bean
    public AmazonS3Client amazonS3Client(LocalStackContainer localStackContainer) {
        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                .withEndpointConfiguration(localStackContainer.getEndpointConfiguration(LocalStackContainer.Service.S3))
                .withCredentials(localStackContainer.getDefaultCredentialsProvider())
                .build();
    }
    @Bean
    public ImageUtils ImageUtils(LocalStackContainer localStackContainer) {
        return new S3ImageUtils(amazonS3Client(localStackContainer));
    }
    @Bean
    ServletWebServerFactory servletWebServerFactory(){
        return new TomcatServletWebServerFactory();
    }
}
- 스프링 빈을 오버라이딩할 테스트용 설정 추가
@TestConfiguration 사용 시 기존 스프링 빈을 사용하는 문제로 인해 test profile에서만 실행되도록 변경 
docker-compose로 실행 시 ServletWebServerFactory를 찾지 못하는 오류로 인해 직접 스프링 빈으로 등록 
 
@ActiveProfiles("test")
@DisplayName("LocalStackS3Test 테스트")
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = LocalStackS3Config.class)
class LocalStackS3Test {
    @Value("${cloud.aws.s3.bucket}")
    String bucket;
    @Autowired
    AmazonS3Client amazonS3Client;
    @BeforeEach
    void beforeEach() {
        amazonS3Client.createBucket(bucket);
    }
    @Test
    void s3_이미지_업로드_테스트() throws IOException {
        
        String content = "hello world";
        String key = "s3-key";
        
        amazonS3Client.putObject(bucket, key, content);
        List<String> result = IOUtils.readLines(amazonS3Client.getObject(bucket, key).getObjectContent(), "utf-8");
        
        assertEquals(1, result.size());
        assertEquals(content, result.get(0));
    }
}

- 정상적으로 테스트가 통과하는 것을 확인할 수 있음
 
문제점
LocalStack을 로컬 환경에서도 Mocking해서 사용하고자 적용시키려고 함  
[containers-ryuk] o.testcontainers.utility.ResourceReaper  : Can not connect to Ryuk at 172.17.0.1:50701
- 로컬이 아닌 
docker 환경에서 실행 시 위와 같은 문제 발생 

- 정상적으로 
Testcontainers와 스프링 부트 애플리케이션이 실행되고 있음 
- 문제는 포트로, 호스트에서 
docker로 접속할 때에는 50701로 접속해야 하지만 docker 내부의 디폴트 네트워크로는 기존 포트인 8080으로 접속해야 한다고 추측 
version: "3.7"
services:
  database:
    container_name: postgres
    image: postgres:latest
    restart: always
    ports:
      - 5432:5432
    environment:
      POSTGRES_DB: board_db
      POSTGRES_USER: board
      POSTGRES_PASSWORD: board
    volumes:
      - /Users/labtop/intellij/docker-postgres/:/var/lib/postgresql/data
  cache:
    container_name: redis
    image: redis:alpine
    ports:
      - 6379:6379
    volumes:
      - /Users/labtop/intellij/docker-redis/:/data
  application:
    container_name: board
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 8085:8085
    environment:
      SPRING_DATASOURCE_URL: jdbc:postgresql://database:5432/board_db
      SPRING_DATASOURCE_USERNAME: board
      SPRING_DATASOURCE_PASSWORD: board
    depends_on:
      - database
      - cache
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
- 현재 
docker-compose.yml의 상태는 위와 같음
LocalStack에 대한 설정이 없기 때문에 어떤 식으로 올바른 testcontainers의 포트를 바인딩해야 할지 해결하지 못한 상태