From 86f6f8d221891a6e08c9e1e71c0d2ef909f408a8 Mon Sep 17 00:00:00 2001 From: rodom_macbook Date: Thu, 16 Jan 2025 23:21:58 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EB=8B=A4=EC=9D=B4=EC=96=B4?= =?UTF-8?q?=EB=A6=AC/=EC=9D=BC=EA=B8=B0=EB=A5=BC=20=EC=83=9D=EC=84=B1/?= =?UTF-8?q?=EC=88=98=EC=A0=95/=EC=82=AD=EC=A0=9C=20=ED=9B=84=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=EB=A1=9C=EC=A7=81=20=EC=9E=91=EC=84=B1,=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 + .../woozuda/backend/image/entity/Image.java | 23 +- .../image/repository/ImageRepository.java | 11 + .../backend/image/service/ImageService.java | 116 ++++- .../woozuda/backend/image/type/ImageType.java | 6 + .../backend/note/service/NoteService.java | 12 + .../backend/image/ImageServiceTest.java | 407 ++++++++++++++++++ .../backend/image/MakeImgsUrlTest.java | 51 +++ 8 files changed, 623 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/woozuda/backend/image/type/ImageType.java create mode 100644 src/test/java/com/woozuda/backend/image/ImageServiceTest.java create mode 100644 src/test/java/com/woozuda/backend/image/MakeImgsUrlTest.java diff --git a/build.gradle b/build.gradle index c923e993..1b1c1d7e 100644 --- a/build.gradle +++ b/build.gradle @@ -93,6 +93,9 @@ dependencies { //OpenFeign: 외부 API 사용 implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.1.4' + + // html 파싱을 위한 jsoup + implementation 'org.jsoup:jsoup:1.16.1' } tasks.named('test') { diff --git a/src/main/java/com/woozuda/backend/image/entity/Image.java b/src/main/java/com/woozuda/backend/image/entity/Image.java index 1777a3f9..48bc9049 100644 --- a/src/main/java/com/woozuda/backend/image/entity/Image.java +++ b/src/main/java/com/woozuda/backend/image/entity/Image.java @@ -2,11 +2,10 @@ import com.woozuda.backend.global.entity.BaseTimeEntity; +import com.woozuda.backend.image.type.ImageType; import jakarta.persistence.*; import lombok.Getter; -import lombok.Setter; -@Setter @Getter @Entity @Table(name="image") @@ -23,7 +22,13 @@ public class Image extends BaseTimeEntity { @Column(name = "is_linked_to_post") private Boolean isLinkedToPost; - public Image(String imageUrl, Boolean isLinkedToPost) { + @Column(name = "image_type") + private ImageType imageType; + + @Column(name = "connected_id") + private Long connectedId; + + private Image(String imageUrl, Boolean isLinkedToPost) { this.imageUrl = imageUrl; this.isLinkedToPost = isLinkedToPost; } @@ -31,4 +36,16 @@ public Image(String imageUrl, Boolean isLinkedToPost) { public static Image of(String imageUrl, Boolean isLinkedToPost) { return new Image(imageUrl, isLinkedToPost); } + + public void changeLinkedToPost(Boolean isLinkedToPost) { + this.isLinkedToPost = isLinkedToPost; + } + + public void changeImageType(ImageType imageType){ + this.imageType = imageType; + } + + public void changeConectedId(Long connectedId){ + this.connectedId = connectedId; + } } diff --git a/src/main/java/com/woozuda/backend/image/repository/ImageRepository.java b/src/main/java/com/woozuda/backend/image/repository/ImageRepository.java index 6b14370c..8fcb9a41 100644 --- a/src/main/java/com/woozuda/backend/image/repository/ImageRepository.java +++ b/src/main/java/com/woozuda/backend/image/repository/ImageRepository.java @@ -1,7 +1,18 @@ package com.woozuda.backend.image.repository; import com.woozuda.backend.image.entity.Image; +import com.woozuda.backend.image.type.ImageType; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface ImageRepository extends JpaRepository { + + // ImageType 과 ConnectedId 가 일치하는 이미지를 찾는 쿼리 + public List findByImageTypeAndConnectedId(ImageType imageType, Long connectedId); + + // imageUrl이 일치하는 이미지를 찾는 쿼리 (select * from image where image_url IN (image_url1 , image_url2 , ....) + public List findByImageUrlIn(List imageUrls); + + public Image findByImageUrl(String imageUrl); } diff --git a/src/main/java/com/woozuda/backend/image/service/ImageService.java b/src/main/java/com/woozuda/backend/image/service/ImageService.java index 7135f908..decdf84a 100644 --- a/src/main/java/com/woozuda/backend/image/service/ImageService.java +++ b/src/main/java/com/woozuda/backend/image/service/ImageService.java @@ -10,24 +10,34 @@ import com.woozuda.backend.image.dto.ImageDto; import com.woozuda.backend.image.entity.Image; import com.woozuda.backend.image.repository.ImageRepository; +import com.woozuda.backend.image.type.ImageType; +import jakarta.persistence.Column; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.Random; +import java.util.UUID; @Service @RequiredArgsConstructor +@Transactional +@Slf4j public class ImageService { private final S3Client s3Client; private final ImageRepository imageRepository; - - @Transactional public ImageDto uploadImage(MultipartFile multipartFile) throws IOException { // 올릴 이미지가 첨부되지 않았을 경우 @@ -39,6 +49,9 @@ public ImageDto uploadImage(MultipartFile multipartFile) throws IOException { // 파일 이름 추출 String filename = multipartFile.getOriginalFilename(); + String uuid = UUID.randomUUID().toString(); + filename = uuid + "_" +filename; + String bucketname = s3Client.getBucketName(); // 메타데이터 생성 @@ -62,7 +75,104 @@ public ImageDto uploadImage(MultipartFile multipartFile) throws IOException { return new ImageDto(imgUrl); } - @Transactional + // urlContent 를 가공해주는 메서드 + public List makeImgsUrl(ImageType imageType, String urlContent){ + + List imgs = new ArrayList<>(); + + if(imageType == ImageType.NOTE){ + // Note는 content가

안녕하세요

excludeBasicImage(List imageStrings){ + imageStrings.removeIf(image -> image.startsWith("https://kr.object.ncloudstorage.com/woozuda-image/random-image")); + return imageStrings; + } + + public void afterCreate(ImageType imageType, Long connectedId, String content){ + //content에서 imageUrl 추출( 리스트로 변환) + List imagesUrl = makeImgsUrl(imageType, content); + + //기본 이미지 - 주어지는 default 이미지는 제외 (필수는 아니나 혹시 해서 넣어둔 로직) + imagesUrl = excludeBasicImage(imagesUrl); + + List images = imageRepository.findByImageUrlIn(imagesUrl); + + // 영속 상태의 엔티티라 save() 하지 않아도 반영됨 + for(Image image : images){ + image.changeLinkedToPost(true); + image.changeImageType(imageType); + image.changeConectedId(connectedId); + } + } + + public void afterUpdate(ImageType imageType, Long connectedId, String content){ + + List imagesUrl = makeImgsUrl(imageType, content); + + //기본 이미지 - 주어지는 default 이미지는 제외 (필수는 아니나 혹시 해서 넣어둔 로직) + imagesUrl = excludeBasicImage(imagesUrl); + + // 이번에 업데이트할 글에 저장되어있는 그림들 리스트 + List afterImages = imageRepository.findByImageUrlIn(imagesUrl); + boolean[] afterImagesBool = new boolean[afterImages.size()]; + + //기존에 글(다이어리)에 저장되어있던 그림들을 불러옴 + List beforeImages = imageRepository.findByImageTypeAndConnectedId(imageType, connectedId); + boolean[] beforeImagesBool = new boolean[beforeImages.size()]; + + //수정 전과 수정 후에 둘다 있는 이미지는 true 처리 - 그리고 이 이미지들은 수정할 필요 없음. + for(int i=0; i < beforeImages.size(); i++){ + for(int j=0; j < afterImages.size(); j++) { + if (beforeImages.get(i).getImageUrl().equals(afterImages.get(j).getImageUrl())) { + beforeImagesBool[i] = true; + afterImagesBool[j] = true; + } + } + } + + // 수정 전 이미지 리스트 중 false 인 것들은 이번에 수정되면서 삭제된 이미지 임 - 고로 삭제 처리 해줘야 함 + List deleteImagesId = new ArrayList<>(); + for(int i=0; i < beforeImages.size(); i++){ + if(!beforeImagesBool[i]){ + deleteImagesId.add(beforeImages.get(i).getId()); + } + } + imageRepository.deleteAllById(deleteImagesId); + + // 수정 후 이미지 리스트 중 false 인 것들은 이번에 수정되면서 추가된 이미지 임 - 고로 추가 처리 해줘야 함 + for(int j=0; j < afterImages.size(); j++){ + if(!afterImagesBool[j]){ + Image nowImage = afterImages.get(j); + + nowImage.changeLinkedToPost(true); + nowImage.changeImageType(imageType); + nowImage.changeConectedId(connectedId); + } + } + + } + + public void afterDelete(ImageType imageType, Long connectedId){ + List images = imageRepository.findByImageTypeAndConnectedId(imageType, connectedId); + imageRepository.deleteAll(images); + } + + @Transactional(readOnly = true) public ImageDto getRandomImage() { Random random = new Random(); int imageNumber = random.nextInt(10) + 1; diff --git a/src/main/java/com/woozuda/backend/image/type/ImageType.java b/src/main/java/com/woozuda/backend/image/type/ImageType.java new file mode 100644 index 00000000..60a236ab --- /dev/null +++ b/src/main/java/com/woozuda/backend/image/type/ImageType.java @@ -0,0 +1,6 @@ +package com.woozuda.backend.image.type; + +public enum ImageType { + DIARY, + NOTE +} diff --git a/src/main/java/com/woozuda/backend/note/service/NoteService.java b/src/main/java/com/woozuda/backend/note/service/NoteService.java index 9112939e..ec7ce0f6 100644 --- a/src/main/java/com/woozuda/backend/note/service/NoteService.java +++ b/src/main/java/com/woozuda/backend/note/service/NoteService.java @@ -2,6 +2,8 @@ import com.woozuda.backend.diary.entity.Diary; import com.woozuda.backend.diary.repository.DiaryRepository; +import com.woozuda.backend.image.service.ImageService; +import com.woozuda.backend.image.type.ImageType; import com.woozuda.backend.note.dto.request.NoteCondRequestDto; import com.woozuda.backend.note.dto.request.NoteIdRequestDto; import com.woozuda.backend.note.dto.response.DateInfoResponseDto; @@ -33,6 +35,7 @@ public class NoteService { private final NoteRepository noteRepository; private final DiaryRepository diaryRepository; + private final ImageService imageService; /** * 최신순 일기 조회 @@ -105,6 +108,15 @@ public void deleteNotes(String username, NoteIdRequestDto requestDto) { for (Diary diary : diariesToChange) { diary.updateNoteInfo(requestDto.getId()); } + + + //해당 노트에 써있던 이미지들 삭제 + List deleteNoteIds = requestDto.getId(); + + for(Long deleteNoteId : deleteNoteIds){ + imageService.afterDelete(ImageType.NOTE, deleteNoteId); + } + } public NoteCountResponseDto getNoteCount(String username, LocalDate startDate, LocalDate endDate) { diff --git a/src/test/java/com/woozuda/backend/image/ImageServiceTest.java b/src/test/java/com/woozuda/backend/image/ImageServiceTest.java new file mode 100644 index 00000000..08cfbe7c --- /dev/null +++ b/src/test/java/com/woozuda/backend/image/ImageServiceTest.java @@ -0,0 +1,407 @@ +package com.woozuda.backend.image; + +import com.woozuda.backend.image.config.S3Client; +import com.woozuda.backend.image.entity.Image; +import com.woozuda.backend.image.repository.ImageRepository; +import com.woozuda.backend.image.service.ImageService; +import com.woozuda.backend.image.type.ImageType; +import com.woozuda.backend.note.entity.converter.AesEncryptor; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaTest +@Import(ImageService.class) +public class ImageServiceTest { + + @MockBean + private AesEncryptor aesEncryptor; + + @MockBean + private S3Client s3Client; + + @Autowired + private ImageService imageService; + + @Autowired + private ImageRepository imageRepository; + + @BeforeEach + void setUp(){ + imageRepository.deleteAll(); + + List images = new ArrayList<>(); + images.add(Image.of("https://aaa.com", false)); + images.add(Image.of("https://bbb.com", false)); + images.add(Image.of("https://ccc.com", false)); + images.add(Image.of("https://ddd.com", false)); + images.add(Image.of("https://eee.com", false)); + + imageRepository.saveAll(images); + } + // 테스트 해야 할 것 + // 1. 다이어리 / 일기의 생성 + @Test + void 기본이미지_다이어리_생성() { + + // when (랜덤 이미지로 다이어리 생성) + imageService.afterCreate(ImageType.DIARY, 1L, "https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + + // then + Image tempImage1 = imageRepository.findByImageUrl("https://aaa.com"); + assertThat(tempImage1.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage2 = imageRepository.findByImageUrl("https://bbb.com"); + assertThat(tempImage2.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage3 = imageRepository.findByImageUrl("https://ccc.com"); + assertThat(tempImage3.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage4 = imageRepository.findByImageUrl("https://ddd.com"); + assertThat(tempImage4.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage5 = imageRepository.findByImageUrl("https://eee.com"); + assertThat(tempImage5.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage6 = imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + assertThat(tempImage6).isEqualTo(null); + } + + @Test + void 커스텀이미지_다이어리_생성(){ + // when (aaa.com 이라는 커스텀 이미지로 다이어리를 생성했다면) + imageService.afterCreate(ImageType.DIARY, 3L, "https://aaa.com"); + + // then + //aaa.com 은 true 가 되어야 함 + Image tempImage1 = imageRepository.findByImageUrl("https://aaa.com"); + assertThat(tempImage1.getConnectedId()).isEqualTo(3L); + assertThat(tempImage1.getImageType()).isEqualTo(ImageType.DIARY); + assertThat(tempImage1.getIsLinkedToPost()).isEqualTo(true); + + Image tempImage2 = imageRepository.findByImageUrl("https://bbb.com"); + assertThat(tempImage2.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage3 = imageRepository.findByImageUrl("https://ccc.com"); + assertThat(tempImage3.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage4 = imageRepository.findByImageUrl("https://ddd.com"); + assertThat(tempImage4.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage5 = imageRepository.findByImageUrl("https://eee.com"); + assertThat(tempImage5.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage6 = imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + assertThat(tempImage6).isEqualTo(null); + } + + @Test + void 이미지_없는_일기_생성(){ + // when (aaa.com 이라는 커스텀 이미지로 다이어리를 생성했다면) + imageService.afterCreate(ImageType.NOTE, 3L, " 하하하

나는 p 에요

하하하

나는 제목이에요

"); + + // then + //aaa.com 은 true 가 되어야 함 + Image tempImage1 = imageRepository.findByImageUrl("https://aaa.com"); + assertThat(tempImage1.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage2 = imageRepository.findByImageUrl("https://bbb.com"); + assertThat(tempImage2.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage3 = imageRepository.findByImageUrl("https://ccc.com"); + assertThat(tempImage3.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage4 = imageRepository.findByImageUrl("https://ddd.com"); + assertThat(tempImage4.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage5 = imageRepository.findByImageUrl("https://eee.com"); + assertThat(tempImage5.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage6 = imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + assertThat(tempImage6).isEqualTo(null); + } + + @Test + void 이미지_있는_일기_생성(){ + // when (aaa.com 이라는 커스텀 이미지로 다이어리를 생성했다면) + imageService.afterCreate(ImageType.NOTE, 3L, " 하하하

나는 p 에요

나는 제목이에요

"); + + // then + //aaa.com 은 true 가 되어야 함 + + Image tempImage1 = imageRepository.findByImageUrl("https://aaa.com"); + assertThat(tempImage1.getConnectedId()).isEqualTo(3L); + assertThat(tempImage1.getImageType()).isEqualTo(ImageType.NOTE); + assertThat(tempImage1.getIsLinkedToPost()).isEqualTo(true); + + Image tempImage2 = imageRepository.findByImageUrl("https://bbb.com"); + assertThat(tempImage2.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage3 = imageRepository.findByImageUrl("https://ccc.com"); + assertThat(tempImage3.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage4 = imageRepository.findByImageUrl("https://ddd.com"); + assertThat(tempImage4.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage5 = imageRepository.findByImageUrl("https://eee.com"); + assertThat(tempImage5.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage6 = imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + assertThat(tempImage6).isEqualTo(null); + } + + //2. 다이어리 / 일기의 수정 + @Test + void 다이어리_기본이미지에서_기본이미지로_수정(){ + //when + imageService.afterUpdate(ImageType.DIARY, 1L, "https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + + //then + Image tempImage1 = imageRepository.findByImageUrl("https://aaa.com"); + assertThat(tempImage1.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage2 = imageRepository.findByImageUrl("https://bbb.com"); + assertThat(tempImage2.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage3 = imageRepository.findByImageUrl("https://ccc.com"); + assertThat(tempImage3.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage4 = imageRepository.findByImageUrl("https://ddd.com"); + assertThat(tempImage4.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage5 = imageRepository.findByImageUrl("https://eee.com"); + assertThat(tempImage5.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage6 = imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + assertThat(tempImage6).isEqualTo(null); + } + + @Test + void 다이어리_기본이미지에서_커스텀이지미지로_수정(){ + //when + imageService.afterUpdate(ImageType.DIARY, 3L, "https://aaa.com"); + + //then + Image tempImage1 = imageRepository.findByImageUrl("https://aaa.com"); + assertThat(tempImage1.getConnectedId()).isEqualTo(3L); + assertThat(tempImage1.getImageType()).isEqualTo(ImageType.DIARY); + assertThat(tempImage1.getIsLinkedToPost()).isEqualTo(true); + + Image tempImage2 = imageRepository.findByImageUrl("https://bbb.com"); + assertThat(tempImage2.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage3 = imageRepository.findByImageUrl("https://ccc.com"); + assertThat(tempImage3.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage4 = imageRepository.findByImageUrl("https://ddd.com"); + assertThat(tempImage4.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage5 = imageRepository.findByImageUrl("https://eee.com"); + assertThat(tempImage5.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage6 = imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + assertThat(tempImage6).isEqualTo(null); + } + + @Test + void 다이어리_커스텀이미지에서_기본이미지로_수정(){ + //given ( 기존 다이어리는 id 가 3이고, aaa.com 을 표지로 한다고 가정) + + Image prevImage = imageRepository.findByImageUrl("https://aaa.com"); + prevImage.changeImageType(ImageType.DIARY); + prevImage.changeConectedId(3L); + prevImage.changeLinkedToPost(true); + + //when + imageService.afterUpdate(ImageType.DIARY, 3L, "https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + + //then + Image tempImage1 = imageRepository.findByImageUrl("https://aaa.com"); + assertThat(tempImage1).isEqualTo(null); + + Image tempImage2 = imageRepository.findByImageUrl("https://bbb.com"); + assertThat(tempImage2.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage3 = imageRepository.findByImageUrl("https://ccc.com"); + assertThat(tempImage3.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage4 = imageRepository.findByImageUrl("https://ddd.com"); + assertThat(tempImage4.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage5 = imageRepository.findByImageUrl("https://eee.com"); + assertThat(tempImage5.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage6 = imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + assertThat(tempImage6).isEqualTo(null); + } + + @Test + void 일기_수정(){ + //given ( 기존 일기장 id 가 3이고, aaa.com , ccc.com 을 가지고 있던 일기 라고 가정) + Image prevImage = imageRepository.findByImageUrl("https://aaa.com"); + prevImage.changeImageType(ImageType.NOTE); + prevImage.changeConectedId(3L); + prevImage.changeLinkedToPost(true); + + Image prevImage2 = imageRepository.findByImageUrl("https://ccc.com"); + prevImage.changeImageType(ImageType.NOTE); + prevImage.changeConectedId(3L); + prevImage.changeLinkedToPost(true); + + //when ( aaa.com 지우고 bbb.com, ddd.com 추가, ccc.com 은 그대로 ) + imageService.afterUpdate(ImageType.NOTE, 3L, " 하하하

나는 p 에요

나는 제목이에요

" + +" "); + + //then + Image tempImage1 = imageRepository.findByImageUrl("https://aaa.com"); + assertThat(tempImage1).isEqualTo(null); + + Image tempImage2 = imageRepository.findByImageUrl("https://bbb.com"); + assertThat(tempImage2.getConnectedId()).isEqualTo(3L); + assertThat(tempImage2.getImageType()).isEqualTo(ImageType.NOTE); + assertThat(tempImage2.getIsLinkedToPost()).isEqualTo(true); + + Image tempImage3 = imageRepository.findByImageUrl("https://ccc.com"); + assertThat(tempImage3.getConnectedId()).isEqualTo(3L); + assertThat(tempImage3.getImageType()).isEqualTo(ImageType.NOTE); + assertThat(tempImage3.getIsLinkedToPost()).isEqualTo(true); + + Image tempImage4 = imageRepository.findByImageUrl("https://ddd.com"); + assertThat(tempImage4.getConnectedId()).isEqualTo(3L); + assertThat(tempImage4.getImageType()).isEqualTo(ImageType.NOTE); + assertThat(tempImage4.getIsLinkedToPost()).isEqualTo(true); + + Image tempImage5 = imageRepository.findByImageUrl("https://eee.com"); + assertThat(tempImage5.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage6 = imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + assertThat(tempImage6).isEqualTo(null); + } + + + //3. 다이어리 / 일기의 삭제 + @Test + void 커스텀이미지_다이어리_삭제(){ + //given (다이어리 id 가 3이고 aaa.com 을 표지로 삼고 있음) + Image prevImage = imageRepository.findByImageUrl("https://aaa.com"); + prevImage.changeImageType(ImageType.DIARY); + prevImage.changeConectedId(3L); + prevImage.changeLinkedToPost(true); + + //when ( aaa.com 지우고 bbb.com, ddd.com 추가, ccc.com 은 그대로 ) + imageService.afterDelete(ImageType.DIARY, 3L); + + //then + Image tempImage1 = imageRepository.findByImageUrl("https://aaa.com"); + assertThat(tempImage1).isEqualTo(null); + + Image tempImage2 = imageRepository.findByImageUrl("https://bbb.com"); + assertThat(tempImage2.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage3 = imageRepository.findByImageUrl("https://ccc.com"); + assertThat(tempImage3.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage4 = imageRepository.findByImageUrl("https://ddd.com"); + assertThat(tempImage4.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage5 = imageRepository.findByImageUrl("https://eee.com"); + assertThat(tempImage5.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage6 = imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + assertThat(tempImage6).isEqualTo(null); + } + + @Test + void 기본이미지_다이어리_삭제(){ + //given + + //when ( aaa.com 지우고 bbb.com, ddd.com 추가, ccc.com 은 그대로 ) + imageService.afterDelete(ImageType.NOTE, 3L); + + //then + Image tempImage1 = imageRepository.findByImageUrl("https://aaa.com"); + assertThat(tempImage1.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage2 = imageRepository.findByImageUrl("https://bbb.com"); + assertThat(tempImage2.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage3 = imageRepository.findByImageUrl("https://ccc.com"); + assertThat(tempImage3.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage4 = imageRepository.findByImageUrl("https://ddd.com"); + assertThat(tempImage4.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage5 = imageRepository.findByImageUrl("https://eee.com"); + assertThat(tempImage5.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage6 = imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + assertThat(tempImage6).isEqualTo(null); + } + + @Test + void 이미지있는_일기_삭제(){ + //given (다이어리 id 가 3이고 aaa.com 을 표지로 삼고 있음) + Image prevImage = imageRepository.findByImageUrl("https://aaa.com"); + prevImage.changeImageType(ImageType.NOTE); + prevImage.changeConectedId(3L); + prevImage.changeLinkedToPost(true); + + //when ( aaa.com 지우고 bbb.com, ddd.com 추가, ccc.com 은 그대로 ) + imageService.afterDelete(ImageType.NOTE, 3L); + + //then + Image tempImage1 = imageRepository.findByImageUrl("https://aaa.com"); + assertThat(tempImage1).isEqualTo(null); + + Image tempImage2 = imageRepository.findByImageUrl("https://bbb.com"); + assertThat(tempImage2.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage3 = imageRepository.findByImageUrl("https://ccc.com"); + assertThat(tempImage3.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage4 = imageRepository.findByImageUrl("https://ddd.com"); + assertThat(tempImage4.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage5 = imageRepository.findByImageUrl("https://eee.com"); + assertThat(tempImage5.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage6 = imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + assertThat(tempImage6).isEqualTo(null); + } + + @Test + void 이미지없는_일기_삭제(){ + //given (다이어리 id 가 3이고 aaa.com 을 표지로 삼고 있음) + + //when ( aaa.com 지우고 bbb.com, ddd.com 추가, ccc.com 은 그대로 ) + imageService.afterDelete(ImageType.DIARY, 3L); + + //then + Image tempImage1 = imageRepository.findByImageUrl("https://aaa.com"); + assertThat(tempImage1.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage2 = imageRepository.findByImageUrl("https://bbb.com"); + assertThat(tempImage2.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage3 = imageRepository.findByImageUrl("https://ccc.com"); + assertThat(tempImage3.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage4 = imageRepository.findByImageUrl("https://ddd.com"); + assertThat(tempImage4.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage5 = imageRepository.findByImageUrl("https://eee.com"); + assertThat(tempImage5.getIsLinkedToPost()).isEqualTo(false); + + Image tempImage6 = imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/woozuda-image/random-image/random-image-3.jpg"); + assertThat(tempImage6).isEqualTo(null); + } + +} diff --git a/src/test/java/com/woozuda/backend/image/MakeImgsUrlTest.java b/src/test/java/com/woozuda/backend/image/MakeImgsUrlTest.java new file mode 100644 index 00000000..4f1e1f9e --- /dev/null +++ b/src/test/java/com/woozuda/backend/image/MakeImgsUrlTest.java @@ -0,0 +1,51 @@ +package com.woozuda.backend.image; + +import com.woozuda.backend.image.config.S3Client; +import com.woozuda.backend.image.repository.ImageRepository; +import com.woozuda.backend.image.service.ImageService; +import com.woozuda.backend.image.type.ImageType; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(MockitoExtension.class) +public class MakeImgsUrlTest { + + @InjectMocks + ImageService imageService; + + @Mock + S3Client s3Client; + + @Mock + ImageRepository imageRepository; + + @Test + public void imageUrl_파서_테스트_노트() { + List urls= imageService.makeImgsUrl(ImageType.NOTE, "

나는

운동을 했다

" + + "

나는

잠을 잤다

"); + + assertThat(urls).contains("https://aaa.com", "https://bbb.com"); + } + + @Test + public void imageUrl_파서_테스트_노트_없을때() { + List urls= imageService.makeImgsUrl(ImageType.NOTE, "

나는

운동을 했다

" + + "

나는

잠을 잤다

"); + + assertThat(urls).isEmpty(); + } + + @Test + public void imageUrl_파서_테스트_다이어리() { + List urls= imageService.makeImgsUrl(ImageType.DIARY, "https://aaa.com"); + + assertThat(urls).contains("https://aaa.com"); + } +} From 6582ba61cbbdc9c75fc0e94b65924a89b11d8fa3 Mon Sep 17 00:00:00 2001 From: rodom_macbook Date: Thu, 16 Jan 2025 23:36:12 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EB=8B=A4=EC=9D=B4=EC=96=B4?= =?UTF-8?q?=EB=A6=AC/=EC=9D=BC=EA=B8=B0=20=EC=A1=B0=EC=9E=91=20=EC=8B=9C?= =?UTF-8?q?=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EC=A1=B0=EC=9E=91=20=ED=95=A8=EC=88=98=20=EC=82=BD=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woozuda/backend/diary/service/DiaryService.java | 13 +++++++++++++ .../backend/note/service/CommonNoteService.java | 9 +++++++++ .../backend/note/service/QuestionNoteService.java | 9 +++++++++ 3 files changed, 31 insertions(+) diff --git a/src/main/java/com/woozuda/backend/diary/service/DiaryService.java b/src/main/java/com/woozuda/backend/diary/service/DiaryService.java index 2cf25543..58675e64 100644 --- a/src/main/java/com/woozuda/backend/diary/service/DiaryService.java +++ b/src/main/java/com/woozuda/backend/diary/service/DiaryService.java @@ -11,6 +11,8 @@ import com.woozuda.backend.diary.dto.response.SingleDiaryResponseDto; import com.woozuda.backend.diary.entity.Diary; import com.woozuda.backend.diary.repository.DiaryRepository; +import com.woozuda.backend.image.service.ImageService; +import com.woozuda.backend.image.type.ImageType; import com.woozuda.backend.note.dto.request.NoteCondRequestDto; import com.woozuda.backend.note.dto.response.NoteEntryResponseDto; import com.woozuda.backend.note.dto.response.NoteResponseDto; @@ -40,6 +42,7 @@ public class DiaryService { private final UserRepository userRepository; private final TagRepository tagRepository; private final NoteRepository noteRepository; + private final ImageService imageService; @Transactional(readOnly = true) public DiaryListResponseDto getDairyList(String username) { @@ -100,6 +103,10 @@ public DiaryIdResponseDto saveDiary(String username, DiarySaveRequestDto request } Diary savedDiary = diaryRepository.save(diary); + + // 이미지 테이블 변경(다이어리 생성 시) + imageService.afterCreate(ImageType.DIARY, savedDiary.getId(), requestDto.getImgUrl()); + return new DiaryIdResponseDto(savedDiary.getId()); } @@ -122,6 +129,9 @@ public DiaryIdResponseDto updateDiary(String username, Long diaryId, DiarySaveRe diary.change(requestDto.getTitle(), tags, requestDto.getImgUrl()); } + // 이미지 테이블 반영 (다이어리 변경 시) + imageService.afterUpdate(ImageType.DIARY, diaryId, requestDto.getImgUrl()); + return new DiaryIdResponseDto(foundDiary.get().getId()); } @@ -134,6 +144,9 @@ public void removeDiary(String username, Long diaryId) { throw new IllegalArgumentException("This diary does not belong to the user."); } + // 이미지 테이블 반영 (다이어리 삭제 시) + imageService.afterDelete(ImageType.DIARY, diaryId); + diaryRepository.deleteById(diaryId); } diff --git a/src/main/java/com/woozuda/backend/note/service/CommonNoteService.java b/src/main/java/com/woozuda/backend/note/service/CommonNoteService.java index 3ab14938..ede8cba0 100644 --- a/src/main/java/com/woozuda/backend/note/service/CommonNoteService.java +++ b/src/main/java/com/woozuda/backend/note/service/CommonNoteService.java @@ -4,6 +4,8 @@ import com.woozuda.backend.diary.dto.response.NoteIdResponseDto; import com.woozuda.backend.diary.entity.Diary; import com.woozuda.backend.diary.repository.DiaryRepository; +import com.woozuda.backend.image.service.ImageService; +import com.woozuda.backend.image.type.ImageType; import com.woozuda.backend.note.dto.request.CommonNoteModifyRequestDto; import com.woozuda.backend.note.dto.request.CommonNoteSaveRequestDto; import com.woozuda.backend.note.dto.response.NoteResponseDto; @@ -33,6 +35,7 @@ public class CommonNoteService { private final NoteRepository noteRepository; private final DiaryRepository diaryRepository; private final AlarmService alarmService; + private final ImageService imageService; public NoteIdResponseDto saveCommonNote(String username, CommonNoteSaveRequestDto requestDto) { Diary foundDiary = diaryRepository.searchDiary(requestDto.getDiaryId(), username); @@ -57,6 +60,9 @@ public NoteIdResponseDto saveCommonNote(String username, CommonNoteSaveRequestDt // 이번에 저장한 자유일기가 그 주의 3번째 일기라면(자유일기 + 질문일기 기준), 알람을 발생합니다. alarmService.threePostAlarm(username, requestDto.getDate()); + // 이미지 테이블 반영 (자유일기 생성 후) + imageService.afterCreate(ImageType.NOTE, savedCommonNote.getId(), requestDto.getContent()); + return NoteIdResponseDto.of(savedCommonNote.getId()); } @@ -85,6 +91,9 @@ public NoteIdResponseDto updateCommonNote(String username, Long noteId, CommonNo requestDto.getContent() ); + // 이미지 테이블 반영 (자유일기 변경 후) + imageService.afterUpdate(ImageType.NOTE, noteId, requestDto.getContent()); + return NoteIdResponseDto.of(foundNote.getId()); } } diff --git a/src/main/java/com/woozuda/backend/note/service/QuestionNoteService.java b/src/main/java/com/woozuda/backend/note/service/QuestionNoteService.java index 0acb709e..595538fd 100644 --- a/src/main/java/com/woozuda/backend/note/service/QuestionNoteService.java +++ b/src/main/java/com/woozuda/backend/note/service/QuestionNoteService.java @@ -4,6 +4,8 @@ import com.woozuda.backend.diary.dto.response.NoteIdResponseDto; import com.woozuda.backend.diary.entity.Diary; import com.woozuda.backend.diary.repository.DiaryRepository; +import com.woozuda.backend.image.service.ImageService; +import com.woozuda.backend.image.type.ImageType; import com.woozuda.backend.note.dto.request.QuestionNoteModifyRequestDto; import com.woozuda.backend.note.dto.request.QuestionNoteSaveRequestDto; import com.woozuda.backend.note.dto.response.NoteResponseDto; @@ -35,6 +37,7 @@ public class QuestionNoteService { private final DiaryRepository diaryRepository; private final QuestionRepository questionRepository; private final AlarmService alarmService; + private final ImageService imageService; public NoteIdResponseDto saveQuestionNote(String username, QuestionNoteSaveRequestDto requestDto) { Diary foundDiary = diaryRepository.searchDiary(requestDto.getDiaryId(), username); @@ -63,6 +66,9 @@ public NoteIdResponseDto saveQuestionNote(String username, QuestionNoteSaveReque // 이번에 저장한 질문일기가 그 주의 3번째 일기라면(자유일기 + 질문일기 기준), 알람을 발생합니다. alarmService.threePostAlarm(username, requestDto.getDate()); + // 이미지 테이블 반영 (질문 일기 생성 후) + imageService.afterCreate(ImageType.NOTE, savedQuestionNote.getId(), requestDto.getContent()); + return NoteIdResponseDto.of(savedQuestionNote.getId()); } @@ -90,6 +96,9 @@ public NoteIdResponseDto updateQuestionNote(String username, Long noteId, Questi requestDto.getContent() ); + // 이미지 테이블 반영 (질문 일기 변경 후) + imageService.afterUpdate(ImageType.NOTE, noteId, requestDto.getContent()); + return NoteIdResponseDto.of(foundNote.getId()); } } From fe3672d2f866f7e5de7953142d3aef2a3ba76898 Mon Sep 17 00:00:00 2001 From: rodom_macbook Date: Fri, 17 Jan 2025 01:56:40 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=EB=A7=A4=EC=9D=BC=20=EC=98=A4?= =?UTF-8?q?=EC=A0=84=203=EC=8B=9C=EC=97=90=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=20=EC=A0=95=EB=A6=AC=20=ED=81=AC=EB=A1=A0=20=EC=9E=A1=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../image/controller/ImageController.java | 9 +++ .../backend/image/cron/ImageDeleteTask.java | 36 +++++++++++ .../image/repository/ImageRepository.java | 3 + .../backend/image/service/ImageService.java | 5 ++ .../backend/image/ImageDeleteCronTest.java | 64 +++++++++++++++++++ 5 files changed, 117 insertions(+) create mode 100644 src/main/java/com/woozuda/backend/image/cron/ImageDeleteTask.java create mode 100644 src/test/java/com/woozuda/backend/image/ImageDeleteCronTest.java diff --git a/src/main/java/com/woozuda/backend/image/controller/ImageController.java b/src/main/java/com/woozuda/backend/image/controller/ImageController.java index 5c87db9a..1523fff7 100644 --- a/src/main/java/com/woozuda/backend/image/controller/ImageController.java +++ b/src/main/java/com/woozuda/backend/image/controller/ImageController.java @@ -13,6 +13,7 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; +import java.util.List; @RequestMapping("/api/image") @RequiredArgsConstructor @@ -28,6 +29,14 @@ public ResponseEntity uploadImage(MultipartFile multipartFile) throws return ResponseEntity.ok(responseDto); } + /* + @PostMapping("/delete") + public void deleteImage(){ + String url = "https://kr.object.ncloudstorage.com/woozuda-image/test-dummy.png"; + imageService.deleteImage(url.split("/")[4]); + } + */ + // 랜덤 이미지 추출 @GetMapping("/random") public ResponseEntity getRandomImage(){ diff --git a/src/main/java/com/woozuda/backend/image/cron/ImageDeleteTask.java b/src/main/java/com/woozuda/backend/image/cron/ImageDeleteTask.java new file mode 100644 index 00000000..ceb19233 --- /dev/null +++ b/src/main/java/com/woozuda/backend/image/cron/ImageDeleteTask.java @@ -0,0 +1,36 @@ +package com.woozuda.backend.image.cron; + +import com.woozuda.backend.image.entity.Image; +import com.woozuda.backend.image.repository.ImageRepository; +import com.woozuda.backend.image.service.ImageService; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@RequiredArgsConstructor +@Component +public class ImageDeleteTask { + + private final ImageService imageService; + private final ImageRepository imageRepository; + + @Scheduled(cron = "0 0 3 * * *") // 매일 오전 3시 + public void cleanUpImages() { + // 게시물과 연결되지 않은 이미지 조회 + List deleteImages = imageRepository.findByIsLinkedToPost(false); + List deleteImageIds = new ArrayList<>(); + + // 해당 이미지 object storage 에서 삭제 + for(Image deleteImage : deleteImages){ + // 지울 이미지들의 Id 추가 (db 에도 반영 위해서) + deleteImageIds.add(deleteImage.getId()); + imageService.deleteImage(deleteImage.getImageUrl().split("/")[4]); + } + + // db(이미지 테이블) 도 그에 맞추어 삭제 + imageRepository.deleteAllById(deleteImageIds); + } +} diff --git a/src/main/java/com/woozuda/backend/image/repository/ImageRepository.java b/src/main/java/com/woozuda/backend/image/repository/ImageRepository.java index 8fcb9a41..7ac97cc5 100644 --- a/src/main/java/com/woozuda/backend/image/repository/ImageRepository.java +++ b/src/main/java/com/woozuda/backend/image/repository/ImageRepository.java @@ -14,5 +14,8 @@ public interface ImageRepository extends JpaRepository { // imageUrl이 일치하는 이미지를 찾는 쿼리 (select * from image where image_url IN (image_url1 , image_url2 , ....) public List findByImageUrlIn(List imageUrls); + // isLinkedToPost 가 true/false 인 이미지 찾기. + public List findByIsLinkedToPost(Boolean isLinkedToPost); + public Image findByImageUrl(String imageUrl); } diff --git a/src/main/java/com/woozuda/backend/image/service/ImageService.java b/src/main/java/com/woozuda/backend/image/service/ImageService.java index decdf84a..ff79ad9d 100644 --- a/src/main/java/com/woozuda/backend/image/service/ImageService.java +++ b/src/main/java/com/woozuda/backend/image/service/ImageService.java @@ -75,6 +75,11 @@ public ImageDto uploadImage(MultipartFile multipartFile) throws IOException { return new ImageDto(imgUrl); } + public void deleteImage(String filename){ + AmazonS3 s3 = s3Client.getAmazonS3(); + s3.deleteObject(s3Client.getBucketName(), filename); + } + // urlContent 를 가공해주는 메서드 public List makeImgsUrl(ImageType imageType, String urlContent){ diff --git a/src/test/java/com/woozuda/backend/image/ImageDeleteCronTest.java b/src/test/java/com/woozuda/backend/image/ImageDeleteCronTest.java new file mode 100644 index 00000000..296c4815 --- /dev/null +++ b/src/test/java/com/woozuda/backend/image/ImageDeleteCronTest.java @@ -0,0 +1,64 @@ +package com.woozuda.backend.image; + +import com.woozuda.backend.image.config.S3Client; +import com.woozuda.backend.image.cron.ImageDeleteTask; +import com.woozuda.backend.image.entity.Image; +import com.woozuda.backend.image.repository.ImageRepository; +import com.woozuda.backend.image.service.ImageService; +import com.woozuda.backend.note.entity.converter.AesEncryptor; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaTest +@Import(ImageDeleteTask.class) +public class ImageDeleteCronTest { + + @MockBean + private AesEncryptor aesEncryptor; + + @MockBean + private ImageService imageService; + + @Autowired + private ImageDeleteTask imageDeleteTask; + + @Autowired + private ImageRepository imageRepository; + + @BeforeEach + void setUp() { + imageRepository.deleteAll(); + + List images = new ArrayList<>(); + images.add(Image.of("https://kr.object.ncloudstorage.com/test/aaa.com", false)); + images.add(Image.of("https://kr.object.ncloudstorage.com/test/bbb.com", true)); + images.add(Image.of("https://kr.object.ncloudstorage.com/test/ccc.com", false)); + images.add(Image.of("https://kr.object.ncloudstorage.com/test/ddd.com", true)); + images.add(Image.of("https://kr.object.ncloudstorage.com/test/eee.com", false)); + + imageRepository.saveAll(images); + } + + @Test + void 크론잡_테스트() { + //when + imageDeleteTask.cleanUpImages(); + + //then + assertThat(imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/test/aaa.com")).isEqualTo(null); + assertThat(imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/test/ccc.com")).isEqualTo(null); + assertThat(imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/test/eee.com")).isEqualTo(null); + + assertThat(imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/test/bbb.com").getIsLinkedToPost()).isEqualTo(true); + assertThat(imageRepository.findByImageUrl("https://kr.object.ncloudstorage.com/test/ddd.com").getIsLinkedToPost()).isEqualTo(true); + } +}