diff --git a/src/main/java/com/outstagram/outstagram/config/SnowflakeConfig.java b/src/main/java/com/outstagram/outstagram/config/SnowflakeConfig.java index e1e9747..a58dfc0 100644 --- a/src/main/java/com/outstagram/outstagram/config/SnowflakeConfig.java +++ b/src/main/java/com/outstagram/outstagram/config/SnowflakeConfig.java @@ -8,13 +8,8 @@ public class SnowflakeConfig { @Bean - public Snowflake snowflake0() { - return Snowflake.getInstance(0); - } - - @Bean - public Snowflake snowflake1() { - return Snowflake.getInstance(1); + public Snowflake snowflake() { + return new Snowflake(); } } diff --git a/src/main/java/com/outstagram/outstagram/kafka/consumer/NotificationConsumer.java b/src/main/java/com/outstagram/outstagram/kafka/consumer/NotificationConsumer.java index f1ba620..4987c34 100644 --- a/src/main/java/com/outstagram/outstagram/kafka/consumer/NotificationConsumer.java +++ b/src/main/java/com/outstagram/outstagram/kafka/consumer/NotificationConsumer.java @@ -1,5 +1,10 @@ package com.outstagram.outstagram.kafka.consumer; +import static com.outstagram.outstagram.common.constant.DBConst.DB_COUNT; +import static com.outstagram.outstagram.common.constant.KafkaConst.NOTIFICATION_GROUPID; +import static com.outstagram.outstagram.common.constant.KafkaConst.SEND_NOTIFICATION; +import static com.outstagram.outstagram.dto.AlarmType.COMMENT; + import com.outstagram.outstagram.dto.CommentDTO; import com.outstagram.outstagram.dto.NotificationDTO; import com.outstagram.outstagram.dto.PostDTO; @@ -8,20 +13,15 @@ import com.outstagram.outstagram.service.CommentService; import com.outstagram.outstagram.service.NotificationService; import com.outstagram.outstagram.service.PostService; -import com.outstagram.outstagram.util.SnowflakeIdGenerator; +import com.outstagram.outstagram.util.Snowflake; +import java.util.ArrayList; +import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.messaging.handler.annotation.Payload; import org.springframework.stereotype.Component; -import java.util.ArrayList; -import java.util.List; - -import static com.outstagram.outstagram.common.constant.KafkaConst.NOTIFICATION_GROUPID; -import static com.outstagram.outstagram.common.constant.KafkaConst.SEND_NOTIFICATION; -import static com.outstagram.outstagram.dto.AlarmType.COMMENT; - @Component @RequiredArgsConstructor @Slf4j @@ -33,7 +33,7 @@ public class NotificationConsumer { private final CommentService commentService; - private final SnowflakeIdGenerator idGenerator; + private final Snowflake snowflake; // TODO : toId에게 이메일 보내는걸로 리팩토링 @KafkaListener(topics = SEND_NOTIFICATION, groupId = NOTIFICATION_GROUPID, containerFactory = "notificationKafkaListenerContainerFactory") @@ -80,7 +80,7 @@ public void receive(@Payload NotificationDTO notification) { } for (NotificationDTO noti : notificationsToSend) { - long notiId = idGenerator.snowflakeIdGenerator(noti.getFromId()); + long notiId = snowflake.nextId(noti.getFromId() % DB_COUNT); noti.setId(notiId); notificationService.insertNotification(noti); log.info("Notification[{}] sent: from user {} to user {}, type: {}\n", noti.getId(), noti.getFromId(), noti.getToId(), noti.getAlarmType()); diff --git a/src/main/java/com/outstagram/outstagram/service/AbstractBaseImageService.java b/src/main/java/com/outstagram/outstagram/service/AbstractBaseImageService.java index 02c88d4..b4e0155 100644 --- a/src/main/java/com/outstagram/outstagram/service/AbstractBaseImageService.java +++ b/src/main/java/com/outstagram/outstagram/service/AbstractBaseImageService.java @@ -1,33 +1,30 @@ package com.outstagram.outstagram.service; +import static com.outstagram.outstagram.common.constant.CacheConst.IMAGE; + import com.outstagram.outstagram.dto.ImageDTO; import com.outstagram.outstagram.exception.ApiException; import com.outstagram.outstagram.exception.errorcode.ErrorCode; import com.outstagram.outstagram.mapper.ImageMapper; -import com.outstagram.outstagram.util.SnowflakeIdGenerator; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import static com.outstagram.outstagram.common.constant.CacheConst.IMAGE; - @RequiredArgsConstructor public abstract class AbstractBaseImageService implements ImageService { private final ImageMapper imageMapper; - private final SnowflakeIdGenerator idGenerator; @Transactional @Override - public void saveImages(List imgFiles, Long postId, Long userId) { + public void saveImages(List imgFiles, Long postId) { List imageDTOList = new ArrayList<>(); try { @@ -39,7 +36,6 @@ public void saveImages(List imgFiles, Long postId, Long userId) { imageDTOList.add( ImageDTO.builder() - .id(idGenerator.snowflakeIdGenerator(userId)) .postId(postId) .originalImgName(originName) .imgUrl(savedName) diff --git a/src/main/java/com/outstagram/outstagram/service/ImageService.java b/src/main/java/com/outstagram/outstagram/service/ImageService.java index 37f1534..eb54ba3 100644 --- a/src/main/java/com/outstagram/outstagram/service/ImageService.java +++ b/src/main/java/com/outstagram/outstagram/service/ImageService.java @@ -6,7 +6,7 @@ public interface ImageService { - void saveImages(List imgFiles, Long postId, Long userId); + void saveImages(List imgFiles, Long postId); List getImageInfos(Long postId); diff --git a/src/main/java/com/outstagram/outstagram/service/LocalImageService.java b/src/main/java/com/outstagram/outstagram/service/LocalImageService.java index ca2e7af..f2f72ec 100644 --- a/src/main/java/com/outstagram/outstagram/service/LocalImageService.java +++ b/src/main/java/com/outstagram/outstagram/service/LocalImageService.java @@ -4,13 +4,7 @@ import com.outstagram.outstagram.exception.ApiException; import com.outstagram.outstagram.exception.errorcode.ErrorCode; import com.outstagram.outstagram.mapper.ImageMapper; -import com.outstagram.outstagram.util.SnowflakeIdGenerator; import jakarta.annotation.PostConstruct; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -18,6 +12,10 @@ import java.nio.file.Paths; import java.util.List; import java.util.UUID; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; @Slf4j @Service @@ -26,8 +24,8 @@ public class LocalImageService extends AbstractBaseImageService { @Value("com.outstagram.upload.path") private String uploadPath; - public LocalImageService(ImageMapper imageMapper, SnowflakeIdGenerator idGenerator) { - super(imageMapper, idGenerator); + public LocalImageService(ImageMapper imageMapper) { + super(imageMapper); } @PostConstruct diff --git a/src/main/java/com/outstagram/outstagram/service/PostService.java b/src/main/java/com/outstagram/outstagram/service/PostService.java index 78b8eb6..ced59c1 100644 --- a/src/main/java/com/outstagram/outstagram/service/PostService.java +++ b/src/main/java/com/outstagram/outstagram/service/PostService.java @@ -1,13 +1,36 @@ package com.outstagram.outstagram.service; +import static com.outstagram.outstagram.common.constant.CacheConst.IN_CACHE; +import static com.outstagram.outstagram.common.constant.CacheConst.NOT_FOUND; +import static com.outstagram.outstagram.common.constant.CacheConst.POST; +import static com.outstagram.outstagram.common.constant.DBConst.DB_COUNT; +import static com.outstagram.outstagram.common.constant.KafkaConst.POST_UPSERT_TOPIC; +import static com.outstagram.outstagram.common.constant.KafkaConst.SEND_NOTIFICATION; +import static com.outstagram.outstagram.common.constant.PageConst.PAGE_SIZE; +import static com.outstagram.outstagram.common.constant.RedisKeyPrefixConst.FEED; +import static com.outstagram.outstagram.common.constant.RedisKeyPrefixConst.LIKE_COUNT_PREFIX; +import static com.outstagram.outstagram.common.constant.RedisKeyPrefixConst.USER_BOOKMARK_PREFIX; +import static com.outstagram.outstagram.common.constant.RedisKeyPrefixConst.USER_LIKE_PREFIX; +import static com.outstagram.outstagram.dto.AlarmType.COMMENT; +import static com.outstagram.outstagram.dto.AlarmType.LIKE; +import static com.outstagram.outstagram.dto.AlarmType.REPLY; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.outstagram.outstagram.controller.request.CreateCommentReq; import com.outstagram.outstagram.controller.request.CreatePostReq; import com.outstagram.outstagram.controller.request.EditCommentReq; import com.outstagram.outstagram.controller.request.EditPostReq; -import com.outstagram.outstagram.dto.*; +import com.outstagram.outstagram.dto.BookmarkRecordDTO; +import com.outstagram.outstagram.dto.CommentDTO; +import com.outstagram.outstagram.dto.CommentUserDTO; +import com.outstagram.outstagram.dto.ImageDTO; +import com.outstagram.outstagram.dto.LikeCountDTO; +import com.outstagram.outstagram.dto.LikeRecordDTO; +import com.outstagram.outstagram.dto.PostDTO; +import com.outstagram.outstagram.dto.PostDetailsDTO; +import com.outstagram.outstagram.dto.UserDTO; import com.outstagram.outstagram.exception.ApiException; import com.outstagram.outstagram.exception.errorcode.ErrorCode; import com.outstagram.outstagram.kafka.producer.FeedUpdateProducer; @@ -15,7 +38,16 @@ import com.outstagram.outstagram.kafka.producer.PostDeleteProducer; import com.outstagram.outstagram.kafka.producer.PostProducer; import com.outstagram.outstagram.mapper.PostMapper; -import com.outstagram.outstagram.util.SnowflakeIdGenerator; +import com.outstagram.outstagram.util.Snowflake; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.session.ExecutorType; @@ -33,25 +65,11 @@ import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.*; -import java.util.stream.Collectors; - -import static com.outstagram.outstagram.common.constant.CacheConst.*; -import static com.outstagram.outstagram.common.constant.KafkaConst.POST_UPSERT_TOPIC; -import static com.outstagram.outstagram.common.constant.KafkaConst.SEND_NOTIFICATION; -import static com.outstagram.outstagram.common.constant.PageConst.PAGE_SIZE; -import static com.outstagram.outstagram.common.constant.RedisKeyPrefixConst.*; -import static com.outstagram.outstagram.dto.AlarmType.COMMENT; -import static com.outstagram.outstagram.dto.AlarmType.*; - @Slf4j @Service @RequiredArgsConstructor public class PostService { - - private final SnowflakeIdGenerator idGenerator; + private final Snowflake snowflake; private final PostMapper postMapper; private final ImageService imageService; private final UserService userService; @@ -84,7 +102,7 @@ private static PostDTO validatePostExist(Long postId) { @Transactional public void insertPost(CreatePostReq createPostReq, Long userId) { - long postId = idGenerator.snowflakeIdGenerator(userId); + long postId = snowflake.nextId(userId % DB_COUNT); PostDTO newPost = PostDTO.builder() .id(postId) @@ -98,7 +116,7 @@ public void insertPost(CreatePostReq createPostReq, Long userId) { postMapper.insertPost(newPost); // 로컬 디렉토리에 이미지 저장 후, DB에 이미지 정보 저장 - imageService.saveImages(createPostReq.getImgFiles(), postId, userId); + imageService.saveImages(createPostReq.getImgFiles(), postId); // kafka에 메시지 발행 : 팔로워들의 피드목록에 내가 작성한 게시물 ID 넣기 feedUpdateProducer.send("feed", userId, postId); @@ -267,8 +285,7 @@ public void editPost(Long postId, EditPostReq editPostReq, Long userId) { // 추가할 이미지가 있다면 추가하기 if (editPostReq.getImgFiles() != null && !editPostReq.getImgFiles().isEmpty()) { - imageService.saveImages(editPostReq.getImgFiles(), - post.getId(), userId); + imageService.saveImages(editPostReq.getImgFiles(), post.getId()); } // 수정할 내용이 있다면 수정하기 @@ -604,11 +621,8 @@ public List getBookmarkedPostsPlusOne(Long userId, Long lastId) public void addComment(CreateCommentReq commentReq, Long postId, Long userId) { validatePostExist(postId); - long commentId = idGenerator.snowflakeIdGenerator(userId); - // 댓글 객체 생성하기 CommentDTO newComment = CommentDTO.builder() - .id(commentId) .userId(userId) .postId(postId) .parentCommentId(null) @@ -636,11 +650,9 @@ public void addComment(CreateCommentReq commentReq, Long postId, Long commentId, if (comment == null) { throw new ApiException(ErrorCode.COMMENT_NOT_FOUND); } - long replyId = idGenerator.snowflakeIdGenerator(userId); // 대댓글 객체 생성하기 CommentDTO newComment = CommentDTO.builder() - .id(replyId) .userId(userId) .postId(postId) .parentCommentId(commentId) diff --git a/src/main/java/com/outstagram/outstagram/service/S3ImageService.java b/src/main/java/com/outstagram/outstagram/service/S3ImageService.java index 9e574f2..54fea63 100644 --- a/src/main/java/com/outstagram/outstagram/service/S3ImageService.java +++ b/src/main/java/com/outstagram/outstagram/service/S3ImageService.java @@ -9,12 +9,6 @@ import com.outstagram.outstagram.exception.ApiException; import com.outstagram.outstagram.exception.errorcode.ErrorCode; import com.outstagram.outstagram.mapper.ImageMapper; -import com.outstagram.outstagram.util.SnowflakeIdGenerator; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -26,6 +20,10 @@ import java.util.List; import java.util.Objects; import java.util.UUID; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; @Slf4j @Service @@ -36,8 +34,8 @@ public class S3ImageService extends AbstractBaseImageService { @Value("${cloud.aws.s3.bucketName}") private String bucketName; - public S3ImageService(ImageMapper imageMapper, AmazonS3 amazonS3, SnowflakeIdGenerator idGenerator) { - super(imageMapper, idGenerator); + public S3ImageService(ImageMapper imageMapper, AmazonS3 amazonS3) { + super(imageMapper); this.amazonS3 = amazonS3; } diff --git a/src/main/java/com/outstagram/outstagram/service/UserService.java b/src/main/java/com/outstagram/outstagram/service/UserService.java index 51363c2..6649707 100644 --- a/src/main/java/com/outstagram/outstagram/service/UserService.java +++ b/src/main/java/com/outstagram/outstagram/service/UserService.java @@ -28,8 +28,7 @@ @Service @RequiredArgsConstructor public class UserService { - private final Snowflake snowflake0; - private final Snowflake snowflake1; + private final Snowflake snowflake; private final UserMapper userMapper; private final UserProducer userProducer; @@ -37,12 +36,12 @@ private long generateUserId(LocalDateTime now) { long userId; if (now.getSecond() % DB_COUNT == 0) { do { - userId = snowflake0.nextId(); + userId = snowflake.nextId(0); } while (userId % DB_COUNT != 0); } else { do { - userId = snowflake1.nextId(); + userId = snowflake.nextId(1); } while (userId % DB_COUNT == 0); } diff --git a/src/main/java/com/outstagram/outstagram/util/Snowflake.java b/src/main/java/com/outstagram/outstagram/util/Snowflake.java index dfbec6d..45c241f 100644 --- a/src/main/java/com/outstagram/outstagram/util/Snowflake.java +++ b/src/main/java/com/outstagram/outstagram/util/Snowflake.java @@ -29,7 +29,6 @@ public class Snowflake { private final long nodeId; private final long customEpoch; - //private AtomicLong sequence = new AtomicLong(0L); private volatile long lastTimestamp = -1L; private volatile long sequence = 0L; // 가시성 보장, 동시성 보장X @@ -69,7 +68,7 @@ public static Snowflake getInstance(long nodeId) { return localInstance; } - public synchronized long nextId() { + public synchronized long nextId(long nodeId) { // timestamp 값 구하기 long curTimestamp = timestamp(); diff --git a/src/main/java/com/outstagram/outstagram/util/SnowflakeIdGenerator.java b/src/main/java/com/outstagram/outstagram/util/SnowflakeIdGenerator.java deleted file mode 100644 index 087eae1..0000000 --- a/src/main/java/com/outstagram/outstagram/util/SnowflakeIdGenerator.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.outstagram.outstagram.util; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -import static com.outstagram.outstagram.common.constant.DBConst.DB_COUNT; - -@Component -@RequiredArgsConstructor -public class SnowflakeIdGenerator { - private final Snowflake snowflake0; - private final Snowflake snowflake1; - - public long snowflakeIdGenerator(long userId) { - long nodeId = userId % DB_COUNT; - long id; - if (nodeId == 0) { - id = snowflake0.nextId(); - } else { - id = snowflake1.nextId(); - } - return id; - } -} diff --git a/src/main/resources/mybatis/mapper/comment.xml b/src/main/resources/mybatis/mapper/comment.xml index 359ed83..e9bd26d 100644 --- a/src/main/resources/mybatis/mapper/comment.xml +++ b/src/main/resources/mybatis/mapper/comment.xml @@ -4,8 +4,8 @@ - INSERT INTO comment (id, user_id, post_id, parent_comment_id, contents, level, is_deleted, create_date, update_date) - VALUES (#{id}, #{userId}, #{postId}, #{parentCommentId}, #{contents}, #{level}, #{isDeleted}, #{createDate}, #{updateDate}) + INSERT INTO comment (user_id, post_id, parent_comment_id, contents, level, is_deleted, create_date, update_date) + VALUES (#{userId}, #{postId}, #{parentCommentId}, #{contents}, #{level}, #{isDeleted}, #{createDate}, #{updateDate}) diff --git a/src/main/resources/mybatis/mapper/image.xml b/src/main/resources/mybatis/mapper/image.xml index d50b105..d6f4238 100644 --- a/src/main/resources/mybatis/mapper/image.xml +++ b/src/main/resources/mybatis/mapper/image.xml @@ -4,10 +4,10 @@ - INSERT INTO image (id, post_id, original_img_name, img_url, create_date, update_date) + INSERT INTO image (post_id, original_img_name, img_url, create_date, update_date) VALUES - (#{image.id}, #{image.postId}, #{image.originalImgName}, #{image.imgUrl}, + (#{image.postId}, #{image.originalImgName}, #{image.imgUrl}, #{image.createDate}, #{image.updateDate}) diff --git a/src/test/java/com/outstagram/outstagram/service/NotificationServiceTest.java b/src/test/java/com/outstagram/outstagram/service/NotificationServiceTest.java index 1cffb5b..617d874 100644 --- a/src/test/java/com/outstagram/outstagram/service/NotificationServiceTest.java +++ b/src/test/java/com/outstagram/outstagram/service/NotificationServiceTest.java @@ -1,5 +1,16 @@ package com.outstagram.outstagram.service; +import static com.outstagram.outstagram.common.constant.PageConst.PAGE_SIZE; +import static com.outstagram.outstagram.dto.AlarmType.LIKE; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import com.outstagram.outstagram.dto.ImageDTO; import com.outstagram.outstagram.dto.NotificationDTO; import com.outstagram.outstagram.dto.NotificationDetailsDTO; @@ -7,23 +18,17 @@ import com.outstagram.outstagram.exception.ApiException; import com.outstagram.outstagram.exception.errorcode.ErrorCode; import com.outstagram.outstagram.mapper.NotificationMapper; +import com.outstagram.outstagram.util.Snowflake; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; 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.time.LocalDateTime; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import static com.outstagram.outstagram.common.constant.PageConst.PAGE_SIZE; -import static com.outstagram.outstagram.dto.AlarmType.LIKE; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class NotificationServiceTest { @InjectMocks @@ -38,23 +43,28 @@ class NotificationServiceTest { @Mock private ImageService imageService; + @Mock + private Snowflake snowflake; + @Test public void testInsertNotification_Success() { // given + long notiId = snowflake.nextId(1L); NotificationDTO notification = NotificationDTO.builder() - .fromId(1L) - .toId(2L) - .targetId(1L) - .alarmType(LIKE) - .isRead(false) - .createDate(LocalDateTime.now()) - .updateDate(LocalDateTime.now()) - .build(); + .id(notiId) + .fromId(1L) + .toId(2L) + .targetId(1L) + .alarmType(LIKE) + .isRead(false) + .createDate(LocalDateTime.now()) + .updateDate(LocalDateTime.now()) + .build(); // when notificationService.insertNotification(notification); - when(notificationMapper.findByIdAndUserId(1L, 2L)).thenReturn(notification); - NotificationDTO findNotification = notificationMapper.findByIdAndUserId(1L, 2L); + when(notificationMapper.findByIdAndUserId(notiId, 2L)).thenReturn(notification); + NotificationDTO findNotification = notificationMapper.findByIdAndUserId(notiId, 2L); // then assertEquals(findNotification.getFromId(), notification.getFromId()); diff --git a/src/test/java/com/outstagram/outstagram/service/PostServiceTest.java b/src/test/java/com/outstagram/outstagram/service/PostServiceTest.java index ec1af1e..7e2982e 100644 --- a/src/test/java/com/outstagram/outstagram/service/PostServiceTest.java +++ b/src/test/java/com/outstagram/outstagram/service/PostServiceTest.java @@ -1,11 +1,36 @@ package com.outstagram.outstagram.service; +import static com.outstagram.outstagram.common.constant.PageConst.PAGE_SIZE; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyList; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import com.outstagram.outstagram.controller.request.CreatePostReq; import com.outstagram.outstagram.controller.request.EditPostReq; -import com.outstagram.outstagram.dto.*; +import com.outstagram.outstagram.dto.ImageDTO; +import com.outstagram.outstagram.dto.PostDTO; +import com.outstagram.outstagram.dto.PostDetailsDTO; +import com.outstagram.outstagram.dto.PostImageDTO; +import com.outstagram.outstagram.dto.UserDTO; import com.outstagram.outstagram.exception.ApiException; import com.outstagram.outstagram.exception.errorcode.ErrorCode; +import com.outstagram.outstagram.kafka.producer.FeedUpdateProducer; +import com.outstagram.outstagram.kafka.producer.PostProducer; import com.outstagram.outstagram.mapper.PostMapper; +import com.outstagram.outstagram.util.Snowflake; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -13,15 +38,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.web.multipart.MultipartFile; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static com.outstagram.outstagram.common.constant.PageConst.PAGE_SIZE; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) class PostServiceTest { @@ -40,6 +56,15 @@ class PostServiceTest { @Mock private LikeService likeService; + @Mock + private Snowflake snowflake; + + @Mock + private FeedUpdateProducer feedUpdateProducer; + + @Mock + private PostProducer postProducer; + @Test public void testInsertPost_Success() { // given @@ -48,21 +73,17 @@ public void testInsertPost_Success() { .contents("게시물 내용입니다.") .imgFiles(List.of(mockFile)) .build(); - Long userId = 1L; + long userId = 1L; + long postId = snowflake.nextId(1); + given(snowflake.nextId(1)).willReturn(postId); // when - // postMapper의 insertPost 메서드가 호출될 때, postId를 1L로 세팅 - when(postMapper.insertPost(any(PostDTO.class))).thenAnswer(invocation -> { - PostDTO p = invocation.getArgument(0); - p.setId(1L); - return null; - }); postService.insertPost(createPostReq, userId); // then // PostDTO 타입의 어떤 객체든지 상관 없이 insertPost가 정확히 1번 호출되었는지 검증해주는 코드 verify(postMapper).insertPost(any(PostDTO.class)); -// verify(imageService).saveImages(anyList(), eq(1L)); + verify(imageService).saveImages(anyList(), eq(postId)); } @Test diff --git a/src/test/java/com/outstagram/outstagram/service/UserServiceTest.java b/src/test/java/com/outstagram/outstagram/service/UserServiceTest.java index 6b3b78f..a874000 100644 --- a/src/test/java/com/outstagram/outstagram/service/UserServiceTest.java +++ b/src/test/java/com/outstagram/outstagram/service/UserServiceTest.java @@ -9,8 +9,10 @@ import com.outstagram.outstagram.dto.UserDTO; import com.outstagram.outstagram.exception.ApiException; +import com.outstagram.outstagram.kafka.producer.UserProducer; import com.outstagram.outstagram.mapper.UserMapper; import com.outstagram.outstagram.util.SHA256Util; +import com.outstagram.outstagram.util.Snowflake; import java.time.LocalDateTime; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -25,6 +27,12 @@ public class UserServiceTest { @Mock private UserMapper userMapper; + @Mock + private Snowflake snowflake; + + @Mock + private UserProducer userProducer; + @InjectMocks private UserService userService; @@ -44,6 +52,11 @@ public void testInsertUser_Success() { // given given(userMapper.countByEmail(user.getEmail())).willReturn(0); given(userMapper.countByNickname(user.getNickname())).willReturn(0); + if (user.getCreateDate().getSecond() % 2 == 0) { + given(snowflake.nextId(0)).willReturn(123456L); + } else { + given(snowflake.nextId(1)).willReturn(123457L); + } given(userMapper.insertUser(user)).willReturn(1); // when diff --git a/src/test/java/com/outstagram/outstagram/util/SnowflakeTest.java b/src/test/java/com/outstagram/outstagram/util/SnowflakeTest.java index c9b1674..c93c675 100644 --- a/src/test/java/com/outstagram/outstagram/util/SnowflakeTest.java +++ b/src/test/java/com/outstagram/outstagram/util/SnowflakeTest.java @@ -25,7 +25,7 @@ public void testSingleThreadedSnowflake() { Set ids = new HashSet<>(); for (int i = 0; i < 1000; i++) { - long id = snowflake.nextId(); + long id = snowflake.nextId(0); System.out.println(snowflake.getNodeId() + " " + snowflake.getSequence()); System.out.println(Arrays.toString(snowflake.parse(id))); assertTrue(ids.add(id), "ID는 고유해야 합니다."); @@ -51,7 +51,7 @@ public void testMultiThreadedSnowflake() throws ExecutionException, InterruptedE Callable> task = () -> { Set localIds = new HashSet<>(); for (int i = 0; i < idCount; i++) { - long id = snowflake.nextId(); + long id = snowflake.nextId(0); localIds.add(id); } @@ -90,7 +90,7 @@ public void testDistributedSnowflake() throws Exception { Snowflake snowflake = Snowflake.getInstance(finalNodeId); // 각 노드가 별도의 Snowflake 인스턴스를 사용하도록 수정 Set localIds = new HashSet<>(); for (int i = 0; i < idCount; i++) { - long id = snowflake.nextId(); + long id = snowflake.nextId(finalNodeId); localIds.add(id); // Thread.sleep(2); }