-
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에서 만든 S3Mock 과 findify의 S3 mock library for Java/Scala 가 존재하는 것을 확인하여서 프로젝트에 적용하여 봤다.
S3Mock
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()
)으로 작성하여도 된다.아직 모르는게 많아 게시글에 잘못된 정보가 있을 수 있습니다. 혹시 잘못된 정보가 있다면, 댓글 혹은 메일로 알려주시면 최대한 빨리 수정하겠습니다!
'프로그래밍 > 서버 프로그래밍' 카테고리의 다른 글
Spring Boot + Kotlin + JPA 적용하기 Entity 생성시 생각해볼 점들 (11) 2020.01.28 [JUnit5 , Spring Boot] 인텔리제이에서 JUnit5 DisplayName이 표시되지 않을 때 해결 방법 (1) 2019.12.18 Travis CI를 이용해 Maven + SpringBoot에 CI 적용하기 (0) 2019.02.20 @Valid 에서 받은 Errors를 Serialize해서 ResponseEntity에 담자! (0) 2019.02.19 스프링 시큐리티 요청 URI별 권한 처리할 때 문제상황 해결! (0) 2019.02.19