ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring boot S3 Local에서 Test하기
    프로그래밍/서버 프로그래밍 2019. 4. 4. 19:19

    Spring boot S3 Local에서 Test하기

    문제

    S3를 사용하여 정적 이미지를 업로드 하도록 설정을 하였더니 , 문제가 생겼다. 테스트할 때 마다 실제 s3 저장소에 이미지가 올라간다는 점과, Travis 에서 빌드할 때 accessKey 와 secretKey가 없으니 계속해서 빌드에 실패하는 것이다.

    해결방안

    인터넷에 어떤 블로그에서 실제 회사에서 업무 시 하나의 s3 버킷에 여러명의 개발자가 붙어서 개발하면 다양한 문제가 발생할 수 있기 때문에 로컬에서 테스트시에는 s3 mock을 이용해서 로컬에서 각각의 mock으로 작성된 s3 버킷에서 테스트를 한다는 글을 며칠전에 봤던 것이 기억나는데 아무리 다시 찾아서 읽어보려해도 찾지 못했다…ㅠㅠ

    그래도 그 후 s3 mock 에 관련되서 검색해본 결과 adobe에서 만든 S3MockfindifyS3 mock library for Java/Scala 가 존재하는 것을 확인하여서 프로젝트에 적용하여 봤다.


    S3Mock

    S3Mock


    S3 Mock library for Java/Scala

    S3 Mock library for Java/Scala


    먼저 adobe의 S3Mock이 더 최근까지 관리되고 있는 것을 확인하여 S3Mock을 프로젝트에 적용하였다.

    사이트의 README를 보면서 하나하나 적용하였는데, 중간에 계속 어딘가에서 NullPointException이 발생하는 바람에 결국 사용을 포기하고, S3 Mock library를 적용하였다.

    //pom.xml
        <dependency>
            <groupId>io.findify</groupId>
            <artifactId>s3mock_2.12</artifactId>
            <version>0.2.5</version>
            <scope>test</scope>
        </dependency>

    pom.xml에 dependency를 추가해주었다. ( 링크의 사이트의 예제는 0.2.4로 적혀있는데 0.2.5버전이 존재하므로 0.2.5를 사용해주자. )

    이 후 S3MockConfig라는 TestConfiguration을 작성하여 주었다.

    @TestConfiguration
    public class S3MockConfig {
    
    //@Value는 Properties에서 값을 가져온다.
        @Value("${cloud.aws.region.static}")
        String region;
    
        @Value("${cloud.aws.s3.bucket}")
        String bucket;
    
    //S3Mock을 빌드할때 포트나 메모리에 저장할 지 실제로 저장할 지 같은 것 등등을 설정 가능하다.
        @Bean
        public S3Mock s3Mock() {
            return new S3Mock.Builder().withPort(8001).withInMemoryBackend().build();
        }
    
    //위에서 작성한 S3Mock을 주입받는 Bean을 작성하였다.
    //실제 테스트가 아닌 환경을 위해 작성된 Config환경과 같이 켜질 경우를 대비하여 @Primary를 넣어주었다.
    //s3Mock.start를 이용하여 Mock S3 서버를 로컬에서 시작한다.
        @Bean
        @Primary
        public AmazonS3 amazonS3(S3Mock s3Mock){
            s3Mock.start();
            AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration("http://localhost:8001", region);
            AmazonS3 client = AmazonS3ClientBuilder
                    .standard()
                    .withPathStyleAccessEnabled(true)
                    .withEndpointConfiguration(endpoint)
                    .withCredentials(new AWSStaticCredentialsProvider(new AnonymousAWSCredentials()))
                    .build();
            client.createBucket(bucket);
    
            return client;
        }
    }

    이렇게 작성하여서 AmazonS3라는 bean을 작성하여 준 뒤, 테스트 코드를 작성하였다.

    테스트 코드는 S3ImageUploader라는 클래스가 실제로 잘 작동하는 지를 테스트한다.

    @SpringBootTest
    @RunWith(SpringRunner.class)
    @ActiveProfiles("test")
    @Import(S3MockConfig.class)
    public class S3ImageUploaderTest {
    
        @Autowired
        S3ImageUploader s3ImageUploader;
        @Autowired
        S3Mock s3Mock;
    
        @Test
        public void test() throws IOException {
            String expected = "mock1.png";
            MockMultipartFile mockMultipartFile = new MockMultipartFile("file", expected,
                    "image/png", "test data".getBytes());
            UploadedImageDto uploadedImageDto = s3ImageUploader.upload(mockMultipartFile, "static");
    
            assertThat(uploadedImageDto.getImageExtension()).isEqualTo("png");
            assertThat(uploadedImageDto.getOriginalName()).isEqualTo(expected);
        }
    
        @After
        public void shutdownMockS3(){
            s3Mock.stop();
        }
    }

    위에서 작성한 S3MockConfig를 @Import 어노테이션으로 임포트 해주었다.

    이 후 잘 작동하는 것을 잘 테스트하고, @After 어노테이션으로 만든 메소드에서 s3Mock을 멈추었다. (s3Mock.shutdown())으로 작성하여도 된다.

    아직 모르는게 많아 게시글에 잘못된 정보가 있을 수 있습니다. 혹시 잘못된 정보가 있다면, 댓글 혹은 메일로 알려주시면 최대한 빨리 수정하겠습니다!

    댓글

Designed by Tistory.