diff --git a/mysql/schema.sql b/mysql/schema.sql index 642b48a9..fec82711 100644 --- a/mysql/schema.sql +++ b/mysql/schema.sql @@ -46,3 +46,19 @@ CREATE TABLE posts FOREIGN KEY (user_id) REFERENCES users (id) ); + +CREATE TABLE likes +( + id BIGINT AUTO_INCREMENT, + user_id BIGINT NOT NULL, + post_id BIGINT NOT NULL, + status TINYINT NOT NULL, + created_at DATETIME(6) NULL, + updated_at DATETIME(6) NULL, + CONSTRAINT posts_pk + PRIMARY KEY (id), + FOREIGN KEY (user_id) + REFERENCES users (id), + FOREIGN KEY (post_id) + REFERENCES posts (id) +); diff --git a/src/main/java/com/backendoori/ootw/exception/ImageUploadException.java b/src/main/java/com/backendoori/ootw/exception/ImageUploadException.java index b9646bc0..b682b9bb 100644 --- a/src/main/java/com/backendoori/ootw/exception/ImageUploadException.java +++ b/src/main/java/com/backendoori/ootw/exception/ImageUploadException.java @@ -5,7 +5,7 @@ @Getter @RequiredArgsConstructor -public class ImageUploadException extends RuntimeException{ +public class ImageUploadException extends RuntimeException { private final String message = "이미지 업로드 중 예외가 발생했습니다."; diff --git a/src/main/java/com/backendoori/ootw/like/controller/LikeController.java b/src/main/java/com/backendoori/ootw/like/controller/LikeController.java new file mode 100644 index 00000000..f4245d52 --- /dev/null +++ b/src/main/java/com/backendoori/ootw/like/controller/LikeController.java @@ -0,0 +1,29 @@ +package com.backendoori.ootw.like.controller; + +import com.backendoori.ootw.like.dto.controller.LikeRequest; +import com.backendoori.ootw.like.dto.controller.LikeResponse; +import com.backendoori.ootw.like.service.LikeService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/likes") +public class LikeController { + + private final LikeService likeService; + + @PostMapping + public ResponseEntity pushLike(Authentication authentication, + @Valid @RequestBody LikeRequest requestDto) { + Long userId = (Long) authentication.getPrincipal(); + return ResponseEntity.ok(likeService.requestLike(userId, requestDto.postId())); + } + +} diff --git a/src/main/java/com/backendoori/ootw/like/domain/Like.java b/src/main/java/com/backendoori/ootw/like/domain/Like.java new file mode 100644 index 00000000..98f41a99 --- /dev/null +++ b/src/main/java/com/backendoori/ootw/like/domain/Like.java @@ -0,0 +1,58 @@ +package com.backendoori.ootw.like.domain; + +import com.backendoori.ootw.common.BaseEntity; +import com.backendoori.ootw.post.domain.Post; +import com.backendoori.ootw.user.domain.User; +import io.jsonwebtoken.lang.Assert; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Table(name = "likes") +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Like extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id", nullable = false) + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id", nullable = false) + private Post post; + + @Column(name = "status", columnDefinition = "tinyint") + private Boolean status; + + private Like(Long id, User user, Post post, Boolean status) { + Assert.notNull(user); + Assert.notNull(post); + Assert.notNull(status); + this.id = id; + this.user = user; + this.post = post; + this.status = status; + } + + public void updateStatus() { + this.status = !status; + } + +} diff --git a/src/main/java/com/backendoori/ootw/like/dto/controller/LikeRequest.java b/src/main/java/com/backendoori/ootw/like/dto/controller/LikeRequest.java new file mode 100644 index 00000000..5fd8a3fb --- /dev/null +++ b/src/main/java/com/backendoori/ootw/like/dto/controller/LikeRequest.java @@ -0,0 +1,15 @@ +package com.backendoori.ootw.like.dto.controller; + +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; + +public record LikeRequest( + @Positive + @NotNull(message = NULL_MESSAGE) + Long postId +) { + + private static final String NULL_MESSAGE = "반드시 postId 값이 null 입니다."; + +} diff --git a/src/main/java/com/backendoori/ootw/like/dto/controller/LikeResponse.java b/src/main/java/com/backendoori/ootw/like/dto/controller/LikeResponse.java new file mode 100644 index 00000000..168130f3 --- /dev/null +++ b/src/main/java/com/backendoori/ootw/like/dto/controller/LikeResponse.java @@ -0,0 +1,20 @@ +package com.backendoori.ootw.like.dto.controller; + +import com.backendoori.ootw.like.domain.Like; + +public record LikeResponse( + Long likeId, + Long userId, + Long postId, + boolean status +) { + + public static LikeResponse from(Like like) { + return new LikeResponse( + like.getId(), + like.getUser().getId(), + like.getPost().getId(), + like.getStatus()); + } + +} diff --git a/src/main/java/com/backendoori/ootw/like/repository/LikeRepository.java b/src/main/java/com/backendoori/ootw/like/repository/LikeRepository.java new file mode 100644 index 00000000..a7151797 --- /dev/null +++ b/src/main/java/com/backendoori/ootw/like/repository/LikeRepository.java @@ -0,0 +1,13 @@ +package com.backendoori.ootw.like.repository; + +import java.util.Optional; +import com.backendoori.ootw.like.domain.Like; +import com.backendoori.ootw.post.domain.Post; +import com.backendoori.ootw.user.domain.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface LikeRepository extends JpaRepository { + + Optional findByUserAndPost(User user, Post post); + +} diff --git a/src/main/java/com/backendoori/ootw/like/service/LikeService.java b/src/main/java/com/backendoori/ootw/like/service/LikeService.java new file mode 100644 index 00000000..6011de0c --- /dev/null +++ b/src/main/java/com/backendoori/ootw/like/service/LikeService.java @@ -0,0 +1,59 @@ +package com.backendoori.ootw.like.service; + +import java.util.NoSuchElementException; +import com.backendoori.ootw.exception.UserNotFoundException; +import com.backendoori.ootw.like.domain.Like; +import com.backendoori.ootw.like.dto.controller.LikeResponse; +import com.backendoori.ootw.like.repository.LikeRepository; +import com.backendoori.ootw.post.domain.Post; +import com.backendoori.ootw.post.repository.PostRepository; +import com.backendoori.ootw.user.domain.User; +import com.backendoori.ootw.user.repository.UserRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class LikeService { + + private static final String POST_NOT_FOUND_MESSAGE = "해당 게시글이 존재하지 않습니다."; + private static final String LIKE_NOT_FOUND_MESSAGE = "찾으시는 좋아요 정보가 존재하지 않습니다."; + + private final UserRepository userRepository; + private final PostRepository postRepository; + private final LikeRepository likeRepository; + + @Transactional + public LikeResponse requestLike(Long userId, Long postId) { + User user = userRepository.findById(userId) + .orElseThrow(UserNotFoundException::new); + + Post post = postRepository.findById(postId) + .orElseThrow(() -> new NoSuchElementException(POST_NOT_FOUND_MESSAGE)); + + likeRepository.findByUserAndPost(user, post).ifPresentOrElse( + Like::updateStatus, + likeNotExist(user, post) + ); + + Like like = likeRepository.findByUserAndPost(user, post) + .orElseThrow(() -> new NoSuchElementException(LIKE_NOT_FOUND_MESSAGE)); + + return LikeResponse.from(like); + } + + @NotNull + private Runnable likeNotExist(User user, Post post) { + return () -> { + likeRepository.save( + Like.builder() + .user(user) + .post(post) + .status(true) + .build()); + }; + } + +} diff --git a/src/test/java/com/backendoori/ootw/like/controller/LikeControllerTest.java b/src/test/java/com/backendoori/ootw/like/controller/LikeControllerTest.java new file mode 100644 index 00000000..f254765c --- /dev/null +++ b/src/test/java/com/backendoori/ootw/like/controller/LikeControllerTest.java @@ -0,0 +1,190 @@ +package com.backendoori.ootw.like.controller; + +import static com.backendoori.ootw.security.jwt.JwtAuthenticationFilter.TOKEN_HEADER; +import static com.backendoori.ootw.security.jwt.JwtAuthenticationFilter.TOKEN_PREFIX; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.backendoori.ootw.like.domain.Like; +import com.backendoori.ootw.like.dto.controller.LikeRequest; +import com.backendoori.ootw.like.repository.LikeRepository; +import com.backendoori.ootw.post.controller.PostController; +import com.backendoori.ootw.post.domain.Post; +import com.backendoori.ootw.post.dto.PostSaveRequest; +import com.backendoori.ootw.post.repository.PostRepository; +import com.backendoori.ootw.post.service.PostService; +import com.backendoori.ootw.security.TokenMockMvcTest; +import com.backendoori.ootw.user.domain.User; +import com.backendoori.ootw.user.repository.UserRepository; +import com.backendoori.ootw.weather.dto.WeatherDto; +import jakarta.transaction.Transactional; +import net.datafaker.Faker; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; + +@SpringBootTest +@ExtendWith(MockitoExtension.class) +class LikeControllerTest extends TokenMockMvcTest { + + static final Faker FAKER = new Faker(); + static final WeatherDto weatherDto = new WeatherDto(0.0, -10.0, 10.0, 1, 1); + + User user; + User writer; + + Post post; + + @Autowired + PostController postController; + + @Autowired + PostService postService; + + @Autowired + PostRepository postRepository; + + @Autowired + UserRepository userRepository; + + @Autowired + LikeRepository likeRepository; + + + @BeforeEach + void setup() { + likeRepository.deleteAll(); + postRepository.deleteAll(); + userRepository.deleteAll(); + user = userRepository.save(generateUser()); + writer = userRepository.save(generateUser()); + post = postRepository.save(generatePost(writer)); + setToken(user.getId()); + } + + @AfterEach + void cleanup() { + likeRepository.deleteAll(); + postRepository.deleteAll(); + userRepository.deleteAll(); + } + + private User generateUser() { + return User.builder() + .email(FAKER.internet().emailAddress()) + .password(FAKER.internet().password()) + .nickname(FAKER.internet().username()) + .image(FAKER.internet().url()) + .build(); + } + + private Post generatePost(User user) { + PostSaveRequest postSaveRequest = + new PostSaveRequest("title", FAKER.gameOfThrones().quote(), weatherDto); + return Post.from(user, postSaveRequest, FAKER.internet().url()); + } + + + @Test + @Transactional + @DisplayName("정상적으로 좋아요를 누르면 저장에 성공한다.") + public void likeSuccess() throws Exception { + //given + LikeRequest request = new LikeRequest(post.getId()); + + //when + mockMvc.perform(post("http://localhost:8080/api/v1/likes") + .content(objectMapper.writeValueAsBytes(request)) + .header(TOKEN_HEADER, TOKEN_PREFIX + token) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + ).andExpect(status().isOk()) + .andDo(print()); + + //then + Like byUserAndPost = likeRepository.findByUserAndPost(user, post).get(); + + Assertions.assertThat(byUserAndPost.getPost()).isEqualTo(post); + Assertions.assertThat(byUserAndPost.getUser()).isEqualTo(user); + Assertions.assertThat(byUserAndPost.getStatus()).isEqualTo(true); + + } + + @Test + @Transactional + @DisplayName("이미 좋아요를 누른 경우 좋아요가 취소된다.") + public void likeCancel() throws Exception { + //given + Like like = Like.builder().user(user).post(post).status(true).build(); + likeRepository.save(like); + + LikeRequest request = new LikeRequest(post.getId()); + + //when + mockMvc.perform(post("http://localhost:8080/api/v1/likes") + .content(objectMapper.writeValueAsBytes(request)) + .header(TOKEN_HEADER, TOKEN_PREFIX + token) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + ).andExpect(status().isOk()) + .andDo(print()); + + //then + Like byUserAndPost = likeRepository.findByUserAndPost(user, post).get(); + + Assertions.assertThat(byUserAndPost.getPost()).isEqualTo(post); + Assertions.assertThat(byUserAndPost.getUser()).isEqualTo(user); + Assertions.assertThat(byUserAndPost.getStatus()).isEqualTo(false); + + } + + @ParameterizedTest + @NullSource + @ValueSource(longs = {-1L, 0}) + @DisplayName("유효하지 않은 postId 로 좋아요를 요청하면 실패한다.") + public void likeFailPostNotFound(Long postId) throws Exception { + //given + LikeRequest request = new LikeRequest(postId); + + //when //then + mockMvc.perform(post("http://localhost:8080/api/v1/likes") + .content(objectMapper.writeValueAsBytes(request)) + .header(TOKEN_HEADER, TOKEN_PREFIX + token) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + ).andExpect(status().isBadRequest()) + .andDo(print()); + + } + + @ParameterizedTest + @ValueSource(longs = Long.MAX_VALUE) + @DisplayName("존재하지 않는 post 에 좋아요를 요청하면 실패한다.") + public void likeFailNullPostId(Long postId) throws Exception { + //given + LikeRequest request = new LikeRequest(postId); + + //when //then + mockMvc.perform(post("http://localhost:8080/api/v1/likes") + .content(objectMapper.writeValueAsBytes(request)) + .header(TOKEN_HEADER, TOKEN_PREFIX + token) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + ).andExpect(status().isNotFound()) + .andDo(print()); + + } + +} diff --git a/src/test/java/com/backendoori/ootw/like/domain/LikeTest.java b/src/test/java/com/backendoori/ootw/like/domain/LikeTest.java new file mode 100644 index 00000000..3787f0ee --- /dev/null +++ b/src/test/java/com/backendoori/ootw/like/domain/LikeTest.java @@ -0,0 +1,152 @@ +package com.backendoori.ootw.like.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.backendoori.ootw.post.domain.Post; +import com.backendoori.ootw.post.dto.PostSaveRequest; +import com.backendoori.ootw.user.domain.User; +import com.backendoori.ootw.weather.dto.WeatherDto; +import net.datafaker.Faker; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullSource; + +class LikeTest { + + static final WeatherDto weatherDto = new WeatherDto(0.0, -10.0, 10.0, 1, 1); + + static final Faker FAKER = new Faker(); + + private User generateUser() { + return User.builder() + .id((long) FAKER.number().positive()) + .email(FAKER.internet().emailAddress()) + .password(FAKER.internet().password()) + .nickname(FAKER.internet().username()) + .image(FAKER.internet().url()) + .build(); + } + + private Post generatePost(User user) { + PostSaveRequest postSaveRequest = + new PostSaveRequest("title", FAKER.gameOfThrones().quote(), weatherDto); + return Post.from(user, postSaveRequest, FAKER.internet().url()); + } + + @Test + @DisplayName("정상적으로 Like 객체가 만들어진다.") + public void makeLikeSuccess() { + //given + User user = generateUser(); + User writer = generateUser(); + Post post = generatePost(writer); + + //when, then + assertThatCode(() -> Like.builder() + .user(user) + .post(post) + .status(true) + .build()).doesNotThrowAnyException(); + + assertThatCode(() -> Like.builder() + .user(user) + .post(post) + .status(false) + .build()).doesNotThrowAnyException(); + + } + + @ParameterizedTest + @NullSource + @DisplayName("post가 null 인 경우 좋아요 객체를 생성 시 예외가 발생한다.") + public void makeLikeFailByNullPost(Post post) { + //given + User user = generateUser(); + + //when, then + assertThatThrownBy(() -> Like.builder() + .user(user) + .post(post) + .status(true) + .build()) + .isInstanceOf(IllegalArgumentException.class); + + assertThatThrownBy(() -> Like.builder() + .user(user) + .post(post) + .status(false) + .build()) + .isInstanceOf(IllegalArgumentException.class); + + } + + @ParameterizedTest + @NullSource + @DisplayName("user가 null 인 경우 좋아요 객체를 생성 시 예외가 발생한다.") + public void makeLikeFailByNullUser(User user) { + //given + User writer = generateUser(); + Post post = generatePost(writer); + + //when, then + assertThatThrownBy(() -> Like.builder() + .user(user) + .post(post) + .status(true) + .build()) + .isInstanceOf(IllegalArgumentException.class); + + assertThatThrownBy(() -> Like.builder() + .user(user) + .post(post) + .status(false) + .build()) + .isInstanceOf(IllegalArgumentException.class); + + } + + @Test + @DisplayName("status 값을 주지 않는 경우 예외가 발생한다.") + public void makeLikeFailByNullStatus() { + //given + User user = generateUser(); + User writer = generateUser(); + Post post = generatePost(writer); + + //when, then + assertThatThrownBy(() -> Like.builder() + .user(user) + .post(post) + .build()) + .isInstanceOf(IllegalArgumentException.class); + + } + + @Test + @DisplayName("정상적으로 Like status가 업데이트 된다.") + public void statusUpdateSuccess() { + //given + User user = generateUser(); + User writer = generateUser(); + Post post = generatePost(writer); + + //when, then + Like like = Like.builder() + .user(user) + .post(post) + .status(true) + .build(); + + like.updateStatus(); + assertThat(like.getStatus()).isEqualTo(false); + + like.updateStatus(); + assertThat(like.getStatus()).isEqualTo(true); + + } + + +} diff --git a/src/test/java/com/backendoori/ootw/like/service/LikeServiceTest.java b/src/test/java/com/backendoori/ootw/like/service/LikeServiceTest.java new file mode 100644 index 00000000..1f519aa4 --- /dev/null +++ b/src/test/java/com/backendoori/ootw/like/service/LikeServiceTest.java @@ -0,0 +1,163 @@ +package com.backendoori.ootw.like.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.NoSuchElementException; +import com.backendoori.ootw.exception.UserNotFoundException; +import com.backendoori.ootw.like.domain.Like; +import com.backendoori.ootw.like.dto.controller.LikeResponse; +import com.backendoori.ootw.like.repository.LikeRepository; +import com.backendoori.ootw.post.controller.PostController; +import com.backendoori.ootw.post.domain.Post; +import com.backendoori.ootw.post.dto.PostSaveRequest; +import com.backendoori.ootw.post.repository.PostRepository; +import com.backendoori.ootw.post.service.PostService; +import com.backendoori.ootw.security.TokenMockMvcTest; +import com.backendoori.ootw.user.domain.User; +import com.backendoori.ootw.user.repository.UserRepository; +import com.backendoori.ootw.weather.dto.WeatherDto; +import net.datafaker.Faker; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class LikeServiceTest extends TokenMockMvcTest { + + private static final String POST_NOT_FOUND_MESSAGE = "해당 게시글이 존재하지 않습니다."; + static final WeatherDto weatherDto = new WeatherDto(0.0, -10.0, 10.0, 1, 1); + + static final Faker FAKER = new Faker(); + + User user; + + User writer; + + Post post; + + @Autowired + PostController postController; + + @Autowired + PostService postService; + + @Autowired + PostRepository postRepository; + + @Autowired + UserRepository userRepository; + + @Autowired + LikeRepository likeRepository; + + @Autowired + LikeService likeService; + + + @BeforeEach + void setup() { + likeRepository.deleteAll(); + postRepository.deleteAll(); + userRepository.deleteAll(); + user = userRepository.save(generateUser()); + writer = userRepository.save(generateUser()); + post = postRepository.save(generatePost(writer)); + setToken(user.getId()); + } + + @AfterEach + void cleanup() { + likeRepository.deleteAll(); + postRepository.deleteAll(); + userRepository.deleteAll(); + } + + private User generateUser() { + return User.builder() + .email(FAKER.internet().emailAddress()) + .password(FAKER.internet().password()) + .nickname(FAKER.internet().username()) + .image(FAKER.internet().url()) + .build(); + } + + private Post generatePost(User user) { + PostSaveRequest postSaveRequest = + new PostSaveRequest("title", FAKER.gameOfThrones().quote(), weatherDto); + return Post.from(user, postSaveRequest, FAKER.internet().url()); + } + + @Test + @DisplayName("정상적으로 likeDto를 받아 좋아요를 누르면 성공한다.") + public void likePostSuccess() throws Exception { + //given + Long postId = post.getId(); + Long userId = user.getId(); + + //when + LikeResponse response = likeService.requestLike(userId, postId); + + //then + assertThat(response.postId()).isEqualTo(postId); + assertThat(response.userId()).isEqualTo(userId); + assertThat(response.status()).isEqualTo(true); + + } + + @Test + @DisplayName("이미 좋아요를 누른 게시물의 경우 좋아요가 취소된다.") + public void likePostCancelSuccess() throws Exception { + //given + Like like = Like.builder().user(user).post(post).status(true).build(); + likeRepository.save(like); + Long postId = post.getId(); + Long userId = user.getId(); + + //when + LikeResponse response = likeService.requestLike(userId, postId); + + //then + assertThat(response.postId()).isEqualTo(postId); + assertThat(response.userId()).isEqualTo(userId); + assertThat(response.status()).isEqualTo(false); + + } + + @ParameterizedTest + @ValueSource(longs = {-1, 0, Long.MAX_VALUE}) + @DisplayName("존재하지 않는 게시물에 좋아요를 누르는 경우 요청에 실패한다.") + public void likePostFailWithWrongPostId(Long wrongPostId) { + //given + Long postId = wrongPostId; + Long userId = user.getId(); + + //when, then + assertThatThrownBy(() -> likeService.requestLike(userId, postId)) + .isInstanceOf(NoSuchElementException.class) + .hasMessage(POST_NOT_FOUND_MESSAGE); + + } + + @ParameterizedTest + @ValueSource(longs = {-1, 0, Long.MAX_VALUE}) + @DisplayName("존재하지 않는 유저에 좋아요를 요청한 경우 요청에 실패한다.") + public void likePostFailWithWrongUserId(Long wrongUserId) { + //given + Long postId = post.getId(); + Long userId = wrongUserId; + + //when, then + assertThatThrownBy(() -> likeService.requestLike(userId, postId)) + .isInstanceOf(UserNotFoundException.class) + .hasMessage(UserNotFoundException.DEFAULT_MESSAGE); + + } + + +}