@@ -79,8 +79,7 @@ class UploadBase64ImageTests {
7979
8080 // Then
8181 assertThat (resultUrl ).isNotNull ();
82- assertThat (resultUrl ).startsWith ("https://" + TEST_BUCKET_NAME + ".s3." + TEST_REGION + ".amazonaws.com/" );
83- assertThat (resultUrl ).contains ("scenario-" );
82+ assertThat (resultUrl ).startsWith ("scenario-" );
8483 assertThat (resultUrl ).endsWith (".jpeg" );
8584
8685 // S3Client 호출 검증
@@ -171,7 +170,7 @@ class UploadBase64ImageTests {
171170 String resultUrl = s3StorageService .uploadBase64Image (base64Data ).get ();
172171
173172 // Then - S3 표준 URL 형식: https://{bucket}.s3.{region}.amazonaws.com/{key}
174- assertThat (resultUrl ).matches ("https://test-bucket \\ .s3 \\ .ap-northeast-2 \\ .amazonaws \\ .com/ scenario-[a-f0-9\\ -]+\\ .jpeg" );
173+ assertThat (resultUrl ).matches ("scenario-[a-f0-9\\ -]+\\ .jpeg" );
175174 }
176175 }
177176
@@ -183,46 +182,49 @@ class DeleteImageTests {
183182 @ DisplayName ("성공 - S3 이미지 삭제" )
184183 void deleteImage_성공_S3_이미지_삭제 () throws ExecutionException , InterruptedException {
185184 // Given
186- String s3Url = "https://test-bucket.s3.ap-northeast-2.amazonaws.com/ scenario-test-uuid.jpeg" ;
185+ String key = "scenario-test-uuid.jpeg" ;
187186 DeleteObjectResponse mockResponse = DeleteObjectResponse .builder ().build ();
188187 given (s3Client .deleteObject (any (DeleteObjectRequest .class )))
189188 .willReturn (mockResponse );
190189
191190 // When
192- CompletableFuture <Void > deleteFuture = s3StorageService .deleteImage (s3Url );
191+ CompletableFuture <Void > deleteFuture = s3StorageService .deleteImage (key );
193192 deleteFuture .get ();
194193
195194 // Then
196- verify (s3Client , times (1 )).deleteObject (any (DeleteObjectRequest .class ));
195+ verify (s3Client , times (1 )).deleteObject (argThat ((DeleteObjectRequest request ) ->
196+ request .key ().equals (key )
197+ ));
197198 }
198199
199200 @ Test
200201 @ DisplayName ("실패 - S3 서비스 에러" )
201202 void deleteImage_실패_S3_서비스_에러 () {
202203 // Given
203- String s3Url = "https://test-bucket.s3.ap-northeast-2.amazonaws.com/scenario-test-uuid.jpeg" ;
204-
205- AwsErrorDetails errorDetails = AwsErrorDetails .builder ()
206- .errorMessage ("NoSuchKey" )
207- .build ();
208- S3Exception s3Exception = (S3Exception ) S3Exception .builder ()
209- .awsErrorDetails (errorDetails )
210- .message ("S3 Error" )
211- .build ();
212-
213- doThrow (s3Exception ).when (s3Client ).deleteObject (any (DeleteObjectRequest .class ));
214-
215- // When
216- CompletableFuture <Void > deleteFuture = s3StorageService .deleteImage (s3Url );
217-
218- // Then
219- assertThatThrownBy (deleteFuture ::get )
220- .hasCauseInstanceOf (ApiException .class )
221- .cause ()
222- .hasFieldOrPropertyWithValue ("errorCode" , ErrorCode .S3_CONNECTION_FAILED );
223-
224- verify (s3Client , times (1 )).deleteObject (any (DeleteObjectRequest .class ));
225- }
204+ String key = "scenario-test-uuid.jpeg" ;
205+
206+ AwsErrorDetails errorDetails = AwsErrorDetails .builder ()
207+ .errorMessage ("NoSuchKey" )
208+ .build ();
209+ S3Exception s3Exception = (S3Exception ) S3Exception .builder ()
210+ .awsErrorDetails (errorDetails )
211+ .message ("S3 Error" )
212+ .build ();
213+
214+ doThrow (s3Exception ).when (s3Client ).deleteObject (any (DeleteObjectRequest .class ));
215+
216+ // When
217+ CompletableFuture <Void > deleteFuture = s3StorageService .deleteImage (key );
218+
219+ // Then
220+ assertThatThrownBy (deleteFuture ::get )
221+ .hasCauseInstanceOf (ApiException .class )
222+ .cause ()
223+ .hasFieldOrPropertyWithValue ("errorCode" , ErrorCode .S3_CONNECTION_FAILED );
224+
225+ verify (s3Client , times (1 )).deleteObject (argThat ((DeleteObjectRequest request ) ->
226+ request .key ().equals (key )
227+ )); }
226228
227229 @ Test
228230 @ DisplayName ("실패 - null URL" )
@@ -237,7 +239,7 @@ class DeleteImageTests {
237239 assertThatThrownBy (deleteFuture ::get )
238240 .hasCauseInstanceOf (ApiException .class )
239241 .cause ()
240- .hasFieldOrPropertyWithValue ("errorCode" , ErrorCode .STORAGE_DELETE_FAILED );
242+ .hasFieldOrPropertyWithValue ("errorCode" , ErrorCode .STORAGE_INVALID_FILE );
241243
242244 // S3Client는 호출되지 않아야 함
243245 verify (s3Client , never ()).deleteObject (any (DeleteObjectRequest .class ));
@@ -256,53 +258,13 @@ class DeleteImageTests {
256258 assertThatThrownBy (deleteFuture ::get )
257259 .hasCauseInstanceOf (ApiException .class )
258260 .cause ()
259- .hasFieldOrPropertyWithValue ("errorCode" , ErrorCode .STORAGE_DELETE_FAILED );
261+ .hasFieldOrPropertyWithValue ("errorCode" , ErrorCode .STORAGE_INVALID_FILE );
260262
261263 // S3Client는 호출되지 않아야 함
262264 verify (s3Client , never ()).deleteObject (any (DeleteObjectRequest .class ));
263265 }
264266 }
265267
266- @ Nested
267- @ DisplayName ("URL 파싱" )
268- class ExtractFileNameTests {
269-
270- @ Test
271- @ DisplayName ("성공 - S3 URL에서 파일명 추출" )
272- void extractFileName_성공_S3_URL에서_파일명_추출 () throws ExecutionException , InterruptedException {
273- // Given
274- String s3Url = "https://test-bucket.s3.ap-northeast-2.amazonaws.com/scenario-abc-123.jpeg" ;
275- DeleteObjectResponse mockResponse = DeleteObjectResponse .builder ().build ();
276- given (s3Client .deleteObject (any (DeleteObjectRequest .class )))
277- .willReturn (mockResponse );
278-
279- // When - deleteImage 내부에서 extractFileNameFromUrl 호출됨
280- s3StorageService .deleteImage (s3Url ).get ();
281-
282- // Then - 정상적으로 파일명 추출 및 삭제 요청 성공
283- verify (s3Client , times (1 )).deleteObject (argThat ((DeleteObjectRequest request ) ->
284- request .key ().equals ("scenario-abc-123.jpeg" )
285- ));
286- }
287-
288- @ Test
289- @ DisplayName ("성공 - 복잡한 S3 URL 파싱" )
290- void extractFileName_성공_복잡한_S3_URL_파싱 () throws ExecutionException , InterruptedException {
291- // Given - 경로가 있는 복잡한 URL
292- String complexUrl = "https://test-bucket.s3.ap-northeast-2.amazonaws.com/images/2024/scenario-test.jpeg" ;
293- DeleteObjectResponse mockResponse = DeleteObjectResponse .builder ().build ();
294- given (s3Client .deleteObject (any (DeleteObjectRequest .class )))
295- .willReturn (mockResponse );
296-
297- // When
298- s3StorageService .deleteImage (complexUrl ).get ();
299-
300- // Then - 마지막 부분만 추출
301- verify (s3Client , times (1 )).deleteObject (argThat ((DeleteObjectRequest request ) ->
302- request .key ().equals ("scenario-test.jpeg" )
303- ));
304- }
305- }
306268
307269 @ Nested
308270 @ DisplayName ("스토리지 타입" )
0 commit comments