Skip to content

Commit

Permalink
Merge pull request #221 from kakao-tech-campus-2nd-step3/feature/ISSU…
Browse files Browse the repository at this point in the history
…E-219

[이미지] 테스트 코드 작성
  • Loading branch information
jjt4515 authored Nov 14, 2024
2 parents b4dcd1d + 04f78d0 commit d4890e5
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ public ImageResponse updateImage(Long memberId, Long id, ImageRequest imageReque
Image image = Image.fromResponse(imageResponse);

validateImageOwner(memberId, image.getType(), image.getReferenceId());
validateImageOwner(memberId, imageRequest.type(), imageRequest.referenceId());

if (!image.getType().equals(imageRequest.type()) ||
!image.getReferenceId().equals(imageRequest.referenceId())) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/poomasi/domain/member/entity/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public Member(Long id, String email, String password, Role role, LoginType login
this.role = role;
this.loginType = loginType;
this.provideId = provideId;
this.memberProfile = memberProfile;
this.memberProfile = (memberProfile != null) ? memberProfile : getOrCreateProfile();
this.name = name;
}

Expand Down
217 changes: 217 additions & 0 deletions src/test/java/poomasi/domain/image/service/ImageServiceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
package poomasi.domain.image.service;

import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.*;
import poomasi.domain.image.dto.request.ImageRequest;
import poomasi.domain.image.dto.response.ImageResponse;
import poomasi.domain.image.entity.Image;
import poomasi.domain.image.entity.ImageType;
import poomasi.domain.image.repository.ImageRepository;
import poomasi.domain.image.validator.ImageOwnerValidator;
import poomasi.domain.image.validator.ImageOwnerValidatorFactory;
import poomasi.domain.image.linker.ImageLinkerFactory;
import poomasi.domain.image.deleteLinker.ImageDeleteFactory;
import poomasi.domain.member.entity.Member;
import poomasi.domain.member.service.MemberService;
import poomasi.global.error.BusinessError;
import poomasi.global.error.BusinessException;

import java.util.Optional;

import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

class ImageServiceTest {

@Mock
private ImageRepository imageRepository;

@Mock
private MemberService memberService;

@Mock
private ImageOwnerValidatorFactory validatorFactory;

@Mock
private ImageLinkerFactory imageLinkerFactory;

@Mock
private ImageDeleteFactory imageDeleteFactory;

@InjectMocks
private ImageService imageService;

@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}

@Test
@DisplayName("이미지 저장 성공 테스트")
void saveImage_success() {
// Given
Long memberId = 1L;
ImageRequest imageRequest = new ImageRequest("key", "imageUrl", ImageType.MEMBER_PROFILE, 1L);
Image image = new Image("key", "imageUrl", ImageType.MEMBER_PROFILE, 1L);

when(imageRepository.findByObjectKeyAndTypeAndReferenceId(any(), any(), any()))
.thenReturn(Optional.empty());
when(imageRepository.save(any(Image.class)))
.thenReturn(image);

Member member = mock(Member.class);
when(memberService.findMemberById(memberId)).thenReturn(member);
when(member.isAdmin()).thenReturn(true);

// When
ImageResponse imageResponse = imageService.saveImage(memberId, imageRequest);

// Then
assertNotNull(imageResponse);
assertEquals(image.getObjectKey(), imageResponse.objectKey());
verify(imageRepository, times(1)).save(any(Image.class));
}

@Test
@DisplayName("이미지 저장 실패 테스트 - 개수 초과")
void saveImage_IMAGE_LIMIT_EXCEED() {
// Given
Long memberId = 1L;
ImageRequest imageRequest = new ImageRequest("key", "imageUrl", ImageType.MEMBER_PROFILE, 1L);

when(imageRepository.countByTypeAndReferenceIdAndDeletedAtIsNull(any(), any()))
.thenReturn(1L);

Member member = mock(Member.class);
when(memberService.findMemberById(memberId)).thenReturn(member);

when(imageRepository.countByTypeAndReferenceIdAndDeletedAtIsNull(any(), any()))
.thenReturn(1L);

// When & Then
assertThatThrownBy(() -> imageService.saveImage(memberId, imageRequest))
.isInstanceOf(BusinessException.class)
.hasFieldOrPropertyWithValue("businessError", BusinessError.IMAGE_LIMIT_EXCEED);
}

@Test
@DisplayName("이미지 소유자 검증 실패 테스트")
void validateImageOwner_IMAGE_OWNER_MISMATCH() {
// Given
Long memberId = 1L;
ImageRequest imageRequest = new ImageRequest("key", "imageUrl", ImageType.MEMBER_PROFILE, 1L);

Member member = mock(Member.class);
when(memberService.findMemberById(memberId)).thenReturn(member);
when(member.isAdmin()).thenReturn(false);

ImageOwnerValidator validator = mock(ImageOwnerValidator.class);
when(validatorFactory.getValidator(any())).thenReturn(validator);
when(validator.validateOwner(any(), any())).thenReturn(false);

// When & Then
assertThatThrownBy(() -> imageService.saveImage(memberId, imageRequest))
.isInstanceOf(BusinessException.class)
.hasFieldOrPropertyWithValue("businessError", BusinessError.IMAGE_OWNER_MISMATCH);
}

@Test
@DisplayName("이미지 삭제 성공 테스트")
void deleteImage_success() {
// Given
Long memberId = 1L;
Long imageId = 1L;
Image image = new Image("key", "imageUrl", ImageType.MEMBER_PROFILE, 1L);

Member member = mock(Member.class);
when(memberService.findMemberById(memberId)).thenReturn(member);
when(member.isAdmin()).thenReturn(false);

when(imageRepository.findByIdAndDeletedAtIsNull(imageId))
.thenReturn(Optional.of(image));

// When
imageService.deleteImage(memberId, imageId);

// Then
verify(imageRepository, times(1)).delete(any(Image.class));
}

@Test
@DisplayName("이미지 삭제 실패 테스트 - 이미지 없음")
void deleteImage_IMAGE_NOT_FOUND() {
// Given
Long memberId = 1L;
Long imageId = 1L;

when(imageRepository.findByIdAndDeletedAtIsNull(imageId))
.thenReturn(Optional.empty());

// When & Then
assertThatThrownBy(() -> imageService.deleteImage(memberId, imageId))
.isInstanceOf(BusinessException.class)
.hasFieldOrPropertyWithValue("businessError", BusinessError.IMAGE_NOT_FOUND);
}

@Test
@DisplayName("이미지 업데이트 성공 테스트")
void updateImage_success() {
// Given
Long memberId = 1L;
Long imageId = 1L;
ImageRequest imageRequest = new ImageRequest("newKey", "newImageUrl", ImageType.MEMBER_PROFILE, 1L);

Member member = mock(Member.class);
when(memberService.findMemberById(memberId)).thenReturn(member);
when(member.isAdmin()).thenReturn(false);

Image existingImage = new Image("key", "imageUrl", ImageType.MEMBER_PROFILE, 1L);
when(imageRepository.findByIdAndDeletedAtIsNull(imageId))
.thenReturn(Optional.of(existingImage));

when(imageRepository.save(any(Image.class)))
.thenReturn(existingImage);

// When
ImageResponse imageResponse = imageService.updateImage(memberId, imageId, imageRequest);

// Then
assertNotNull(imageResponse);
assertEquals(imageRequest.objectKey(), "newKey");
assertEquals(imageResponse.objectKey(), "key");
verify(imageRepository, times(1)).save(any(Image.class));
}

@Test
@DisplayName("이미지 수정 실패 - 자신의 이미지가 아님")
void updateImage_IMAGE_OWNER_MISMATCH() {
// Given
Long memberId = 1L;
Long imageId = 1L;
ImageRequest imageRequest = new ImageRequest("newKey", "newImageUrl", ImageType.PRODUCT, 4L);

Member member = mock(Member.class);
when(memberService.findMemberById(memberId)).thenReturn(member);
when(member.isAdmin()).thenReturn(false);

ImageOwnerValidator validator = mock(ImageOwnerValidator.class);
when(validatorFactory.getValidator(any())).thenReturn(validator);
when(validator.validateOwner(any(), any())).thenReturn(false);

Image existingImage = new Image("key", "imageUrl", ImageType.MEMBER_PROFILE, 1L);
when(imageRepository.findByIdAndDeletedAtIsNull(imageId))
.thenReturn(Optional.of(existingImage));

when(imageRepository.save(any(Image.class)))
.thenReturn(existingImage);

assertThatThrownBy(() -> imageService.updateImage(memberId, imageId, imageRequest))
.isInstanceOf(BusinessException.class)
.hasFieldOrPropertyWithValue("businessError", BusinessError.IMAGE_OWNER_MISMATCH);
}
}

0 comments on commit d4890e5

Please sign in to comment.