diff --git a/build.gradle b/build.gradle index 7b75bbb..99d0cb3 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ dependencies { // JWT implementation 'io.jsonwebtoken:jjwt:0.9.1' - // mapstruct + // mapstructㄴ implementation 'org.mapstruct:mapstruct:1.4.2.Final' // lombok @@ -80,6 +80,8 @@ dependencies { // test runtimeOnly 'com.h2database:h2' testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.dbunit:dbunit:2.6.0' + testImplementation 'com.github.springtestdbunit:spring-test-dbunit:1.3.0' } test { diff --git a/src/main/java/com/yapp18/retrospect/config/ErrorInfo.java b/src/main/java/com/yapp18/retrospect/config/ErrorInfo.java index 9d6c8fc..300c274 100644 --- a/src/main/java/com/yapp18/retrospect/config/ErrorInfo.java +++ b/src/main/java/com/yapp18/retrospect/config/ErrorInfo.java @@ -10,7 +10,8 @@ public enum ErrorInfo { TEMPLATE_NULL("EE004", "존재하지 않는 템플릿입니다."), TAG_NULL("EE005", "존재하지 않는 태그입니다."), IMAGE_NULL("EE006", "존재하지 않는 이미지입니다."), - LIKE_NULL("EE007", "존재하지 않는 스크랩입니다."); + LIKE_NULL("EE007", "존재하지 않는 스크랩입니다."), + CONDITION_NULL("EE008","해당 조건에 맞는 회고글이 없습니다."); private final String errorCode; private final String errorMessage; diff --git a/src/main/java/com/yapp18/retrospect/config/JacksonConfiguration.java b/src/main/java/com/yapp18/retrospect/config/JacksonConfig.java similarity index 92% rename from src/main/java/com/yapp18/retrospect/config/JacksonConfiguration.java rename to src/main/java/com/yapp18/retrospect/config/JacksonConfig.java index 06961d4..07da141 100644 --- a/src/main/java/com/yapp18/retrospect/config/JacksonConfiguration.java +++ b/src/main/java/com/yapp18/retrospect/config/JacksonConfig.java @@ -2,9 +2,7 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.*; -import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -16,7 +14,7 @@ import java.util.Locale; @Configuration -public class JacksonConfiguration { +public class JacksonConfig { private final Locale locale = Locale.UK; private final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("MMM dd, yyyy").withLocale(locale); diff --git a/src/main/java/com/yapp18/retrospect/config/QuerydslConfiguration.java b/src/main/java/com/yapp18/retrospect/config/QuerydslConfig.java similarity index 92% rename from src/main/java/com/yapp18/retrospect/config/QuerydslConfiguration.java rename to src/main/java/com/yapp18/retrospect/config/QuerydslConfig.java index b62c21d..5cfaf75 100644 --- a/src/main/java/com/yapp18/retrospect/config/QuerydslConfiguration.java +++ b/src/main/java/com/yapp18/retrospect/config/QuerydslConfig.java @@ -8,7 +8,7 @@ import javax.persistence.PersistenceContext; @Configuration -public class QuerydslConfiguration { +public class QuerydslConfig { @PersistenceContext private EntityManager entityManager; diff --git a/src/main/java/com/yapp18/retrospect/domain/BaseTimeEntity.java b/src/main/java/com/yapp18/retrospect/domain/BaseTimeEntity.java index 622d158..67c734f 100644 --- a/src/main/java/com/yapp18/retrospect/domain/BaseTimeEntity.java +++ b/src/main/java/com/yapp18/retrospect/domain/BaseTimeEntity.java @@ -18,10 +18,10 @@ public abstract class BaseTimeEntity { @CreatedDate// Entity가 생성되어 저장될 때 시간이 자동 저장됩니다. @Column(name ="created_at") - private LocalDateTime createdAt; + protected LocalDateTime createdAt; @LastModifiedDate// 조회한 Entity의 값을 변경할 때 시간이 자동 저장됩니다. @Column(name = "modified_at") - private LocalDateTime modifiedAt; + protected LocalDateTime modifiedAt; } diff --git a/src/main/java/com/yapp18/retrospect/domain/comment/CommentRepository.java b/src/main/java/com/yapp18/retrospect/domain/comment/CommentRepository.java index 809d477..e6247dd 100644 --- a/src/main/java/com/yapp18/retrospect/domain/comment/CommentRepository.java +++ b/src/main/java/com/yapp18/retrospect/domain/comment/CommentRepository.java @@ -3,16 +3,21 @@ import com.yapp18.retrospect.domain.post.Post; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; -import java.time.LocalDateTime; import java.util.List; -import java.util.Optional; public interface CommentRepository extends JpaRepository { - List findAllByPost(Post post, Pageable page); + @Query(value = "SELECT * FROM comment_tb WHERE comment_tb.post_idx = :postIdx", nativeQuery = true) + List findAllByPostIdx(Long postIdx, Pageable page); + +// @Query(value = "SELECT COUNT(*) FROM comment_tb WHERE comment_tb.post_idx = :postIdx", nativeQuery = true) + Long countCommentByPost(Post post); boolean existsByCommentIdxGreaterThanAndPost(Long cursorIdx, Post post); - Long countCommentByPost(Post postIdx); + @Modifying + @Query(value = "ALTER TABLE comment_tb ALTER COLUMN comment_idx RESTART WITH 1", nativeQuery = true) + void restartIdxSequence(); // 테스트 h2 db sequence 초기화용 (postgres에선 사용 불가) } \ No newline at end of file diff --git a/src/main/java/com/yapp18/retrospect/domain/like/Like.java b/src/main/java/com/yapp18/retrospect/domain/like/Like.java index cb6dbc2..fa0b0b2 100644 --- a/src/main/java/com/yapp18/retrospect/domain/like/Like.java +++ b/src/main/java/com/yapp18/retrospect/domain/like/Like.java @@ -35,7 +35,7 @@ public class Like extends BaseTimeEntity { @ManyToOne @JoinColumn(name = "post_idx") - private Post post; // 어떻게..? + private Post post; @ManyToOne @JoinColumn(name = "user_idx") diff --git a/src/main/java/com/yapp18/retrospect/domain/like/LikeRepository.java b/src/main/java/com/yapp18/retrospect/domain/like/LikeRepository.java index a7e04a3..ddeaf07 100644 --- a/src/main/java/com/yapp18/retrospect/domain/like/LikeRepository.java +++ b/src/main/java/com/yapp18/retrospect/domain/like/LikeRepository.java @@ -4,6 +4,7 @@ import com.yapp18.retrospect.domain.user.User; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import java.util.List; @@ -23,6 +24,8 @@ public interface LikeRepository extends JpaRepository { boolean existsByUserAndLikeIdxLessThan(User user, Long lastIdx); void deleteByUserAndPost(User user, Post post); -// List findByUserOrderByCreatedAtDesc(Long userIdx, Pageable page); -// Like findByPostAndUser(Post post, User user); + + @Modifying + @Query(value = "ALTER TABLE like_tb ALTER COLUMN like_idx RESTART WITH 1", nativeQuery = true) + void restartIdxSequence(); // 테스트 h2 db sequence 초기화용 (postgres에선 사용 불가) } \ No newline at end of file diff --git a/src/main/java/com/yapp18/retrospect/domain/post/Post.java b/src/main/java/com/yapp18/retrospect/domain/post/Post.java index 0999fbd..52db163 100644 --- a/src/main/java/com/yapp18/retrospect/domain/post/Post.java +++ b/src/main/java/com/yapp18/retrospect/domain/post/Post.java @@ -17,9 +17,7 @@ import javax.persistence.*; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; @Getter @Setter @@ -56,7 +54,7 @@ public class Post extends BaseTimeEntity { @ManyToOne @JoinColumn(name = "template_idx") - private Template template; // 어떻게? + private Template template; @JsonIgnore @OneToMany(mappedBy = "post",orphanRemoval = true) diff --git a/src/main/java/com/yapp18/retrospect/domain/post/PostRepository.java b/src/main/java/com/yapp18/retrospect/domain/post/PostRepository.java index c52caca..f58bb24 100644 --- a/src/main/java/com/yapp18/retrospect/domain/post/PostRepository.java +++ b/src/main/java/com/yapp18/retrospect/domain/post/PostRepository.java @@ -5,15 +5,13 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; -import java.time.LocalDateTime; import java.util.List; -import java.util.Optional; public interface PostRepository extends JpaRepository { Post findByPostIdx(Long postIdx); - boolean existsByPostIdxLessThan(Long cursorId); + boolean existsByPostIdx(Long postIdx); List findAllByUserUserIdxOrderByCreatedAtDesc(Long userIdx, Pageable pageable); diff --git a/src/main/java/com/yapp18/retrospect/domain/user/Role.java b/src/main/java/com/yapp18/retrospect/domain/user/Role.java index 8eac7d4..9a39580 100644 --- a/src/main/java/com/yapp18/retrospect/domain/user/Role.java +++ b/src/main/java/com/yapp18/retrospect/domain/user/Role.java @@ -6,7 +6,7 @@ @Getter @RequiredArgsConstructor public enum Role { - //스프링 시큐리티에서는 권한 코드에 항상 **ROLE_이 앞에 있어야만 합니다**. + //스프링 시큐리티에서는 권한 코드에 항상 ROLE_이 앞에 있어야만 합니다**. ADMIN("ROLE_ADMIN", "관리자"), MEMBER("ROLE_MEMBER", "일반 회원"), GUEST("ROLE_GUEST", "손님"); diff --git a/src/main/java/com/yapp18/retrospect/domain/user/User.java b/src/main/java/com/yapp18/retrospect/domain/user/User.java index 96cd6a4..6be6dc7 100644 --- a/src/main/java/com/yapp18/retrospect/domain/user/User.java +++ b/src/main/java/com/yapp18/retrospect/domain/user/User.java @@ -3,15 +3,12 @@ import com.sun.istack.NotNull; import com.yapp18.retrospect.domain.BaseTimeEntity; import com.yapp18.retrospect.security.oauth2.AuthProvider; - import lombok.*; import javax.persistence.*; -import java.util.ArrayList; -import java.util.List; +@Getter @Setter @Entity -@Getter @Table(name="user_tb") // 기본 생성자 접근을 protected으로 변경하면 외부에서 해당 생성자를 접근 할 수 없으므로 Builder를 통해서만 객체 생성 가능하므로 안전성 보장 @Builder @@ -60,10 +57,10 @@ public User updateNickname(String nickname){ return this; } - public User updateProfile(String profile, String name, String nickname, String job, String intro){ + public User updateProfile(String name, String nickname, String profile, String job, String intro){ this.name = name; - this.profile = profile; this.nickname = nickname; + this.profile = profile; this.job = job; this.intro = intro; return this; @@ -72,4 +69,6 @@ public User updateProfile(String profile, String name, String nickname, String j public String getRoleKey(){ return this.role.getKey(); } + + } diff --git a/src/main/java/com/yapp18/retrospect/domain/user/UserRepository.java b/src/main/java/com/yapp18/retrospect/domain/user/UserRepository.java index 89fb2c4..2716f04 100644 --- a/src/main/java/com/yapp18/retrospect/domain/user/UserRepository.java +++ b/src/main/java/com/yapp18/retrospect/domain/user/UserRepository.java @@ -1,6 +1,8 @@ package com.yapp18.retrospect.domain.user; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import java.util.Optional; @@ -9,4 +11,8 @@ public interface UserRepository extends JpaRepository { Optional findByEmail(String email); Optional findByUserIdx(Long userIdx); boolean existsByNickname(String nickname); + + @Modifying + @Query(value = "ALTER TABLE user_tb ALTER COLUMN user_idx RESTART WITH 1", nativeQuery = true) + void restartIdxSequence(); // 테스트 h2 db sequence 초기화용 (postgres에선 사용 불가) } diff --git a/src/main/java/com/yapp18/retrospect/service/CommentService.java b/src/main/java/com/yapp18/retrospect/service/CommentService.java index 658cb4b..3d9189a 100644 --- a/src/main/java/com/yapp18/retrospect/service/CommentService.java +++ b/src/main/java/com/yapp18/retrospect/service/CommentService.java @@ -5,53 +5,46 @@ import com.yapp18.retrospect.domain.comment.Comment; import com.yapp18.retrospect.domain.comment.CommentRepository; import com.yapp18.retrospect.domain.post.Post; -import com.yapp18.retrospect.domain.post.PostRepository; import com.yapp18.retrospect.domain.user.User; -import com.yapp18.retrospect.domain.user.UserRepository; -import com.yapp18.retrospect.mapper.CommentMapper; import com.yapp18.retrospect.web.advice.EntityNullException; -import com.yapp18.retrospect.web.dto.ApiPagingResultResponse; -import com.yapp18.retrospect.web.dto.CommentDto; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; -import java.util.stream.Collectors; @RequiredArgsConstructor @Service public class CommentService { + private final PostService postService; private final CommentRepository commentRepository; - private final PostRepository postRepository; @Transactional public Comment inputComments(Comment comment){ //타 서비스 의존성을 제거와 코드 가독성을 위해 Entity 외의 메서드 parameter는 최소화 할 것 - return commentRepository.save(comment); + Long postIdx = comment.getPost().getPostIdx(); + comment.setPost(postService.findByPostIdx(postIdx)); + commentRepository.save(comment); + return comment; // commentRepository.save(comment); 그대로 반환하면 테스트 코드에서 엔티티가 null로 날아옴.. } @Transactional(readOnly = true) - public List getCommmentsListByPostIdx(Long postIdx, Pageable page){ - Post post = postRepository.findById(postIdx) - .orElseThrow(() -> new EntityNullException(ErrorInfo.POST_NULL)); - - return commentRepository.findAllByPost(post, page); + public Comment getCommmentsByIdx(Long commentIdx){ + return commentRepository.findById(commentIdx) + .orElseThrow(() -> new EntityNullException(ErrorInfo.COMMENT_NULL)); } @Transactional(readOnly = true) - public Long getCommmentsCountByPostIdx(Long postIdx){ - Post post = postRepository.findByPostIdx(postIdx); - return commentRepository.countCommentByPost(post); + public List getCommmentsListByPostIdx(Long postIdx, Pageable page){ + return commentRepository.findAllByPostIdx(postIdx, page); } @Transactional(readOnly = true) - public Comment getCommmentsByIdx(Long commentIdx){ - return commentRepository.findById(commentIdx) - .orElseThrow(() -> new EntityNullException(ErrorInfo.COMMENT_NULL)); + public Long getCommmentsCountByPostIdx(Long postIdx){ + Post post = postService.findByPostIdx(postIdx); + return commentRepository.countCommentByPost(post); } @@ -61,7 +54,7 @@ public Comment updateComments(Comment newComment){ Long commentIdx = newComment.getCommentIdx(); Comment oldComment = commentRepository.findById(commentIdx) - .orElseThrow(() -> new EntityNullException(ErrorInfo.COMMENT_NULL)); + .orElseThrow(() -> new EntityNullException(ErrorInfo.COMMENT_NULL)); if(!oldComment.isWriter(newComment.getUser())){ throw new AccessDeniedException(TokenErrorInfo.ACCESS_DENIED.getMessage()); diff --git a/src/main/java/com/yapp18/retrospect/service/CustomOAuth2UserService.java b/src/main/java/com/yapp18/retrospect/service/CustomOAuth2UserService.java index 400ffdd..50beac0 100644 --- a/src/main/java/com/yapp18/retrospect/service/CustomOAuth2UserService.java +++ b/src/main/java/com/yapp18/retrospect/service/CustomOAuth2UserService.java @@ -1,7 +1,5 @@ package com.yapp18.retrospect.service; -import com.yapp18.retrospect.config.AppProperties; -import com.yapp18.retrospect.domain.user.Role; import com.yapp18.retrospect.domain.user.User; import com.yapp18.retrospect.domain.user.UserRepository; import com.yapp18.retrospect.exception.OAuth2AuthenticationProcessingException; @@ -43,7 +41,7 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2Authentic private OAuth2User processOAuth2User(OAuth2UserRequest userRequest, OAuth2User oAuth2User){ String registrationId = userRequest.getClientRegistration().getRegistrationId(); - OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo(registrationId, oAuth2User.getAttributes());; + OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo(registrationId, oAuth2User.getAttributes()); if(!StringUtils.hasText(oAuth2UserInfo.getEmail())) { throw new OAuth2AuthenticationProcessingException("OAuth2 공급자(구글, 카카오, ...) 에서 이메일을 찾을 수 없습니다."); diff --git a/src/main/java/com/yapp18/retrospect/service/PostService.java b/src/main/java/com/yapp18/retrospect/service/PostService.java index 9874fe8..1c23dfa 100644 --- a/src/main/java/com/yapp18/retrospect/service/PostService.java +++ b/src/main/java/com/yapp18/retrospect/service/PostService.java @@ -17,17 +17,17 @@ import com.yapp18.retrospect.web.dto.ApiPagingResultResponse; import com.yapp18.retrospect.web.dto.PostDto; import lombok.RequiredArgsConstructor; - import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; -//import javax.transaction.Transactional; -import java.time.LocalDateTime; + import java.util.List; import java.util.stream.Collectors; +//import javax.transaction.Transactional; + @RequiredArgsConstructor @Service @Transactional @@ -70,25 +70,30 @@ public Post findByPostIdx(Long postIdx){ @Transactional(readOnly = true) public ApiPagingResultResponse getPostsListView(Long cursorId, Pageable page, Long userIdx){ // 마지막으로 검색된 회고글의 조회수 - List result = getPostsView(cursorId, page).stream().map(post->postMapper.postToListResponse(post, userIdx)) + List posts = getPostsView(cursorId, page); + if (posts.isEmpty()) throw new EntityNullException(ErrorInfo.CONDITION_NULL); + + List result = posts.stream().map(post->postMapper.postToListResponse(post, userIdx)) .collect(Collectors.toList()); Long lastIdx = result.isEmpty() ? null : result.get(result.size()-1).getPostIdx(); // 다음 postIdx return new ApiPagingResultResponse<>(isNextView(lastIdx), result); } + // 최신순 @Transactional(readOnly = true) public ApiPagingResultResponse getPostsListCreatedAt(Long cursorIdx, Long userIdx, Pageable pageable){ User user = userRepository.findByUserIdx(userIdx) .orElseThrow(() -> new EntityNullException(ErrorInfo.USER_NULL)); - List postList = cursorIdx == 0 || cursorIdx == null ? + List posts = cursorIdx == 0 || cursorIdx == null ? postRepository.findByUserOrderByCreatedAtDesc(user, pageable) : postRepository.cursorFindByUserOrderByCreatedAtDesc(cursorIdx, user.getUserIdx(), pageable); + if (posts.isEmpty()) throw new EntityNullException(ErrorInfo.CONDITION_NULL); - Long lastIdx = postList.isEmpty() ? null : postList.get(postList.size() - 1).getPostIdx(); // 낮은 조회수 체크 + Long lastIdx = posts.isEmpty() ? null : posts.get(posts.size() - 1).getPostIdx(); // 낮은 조회수 체크 - List result = postList.stream() + List result = posts.stream() .map(post -> postMapper.postToListResponse(post, userIdx)) .collect(Collectors.toList()); @@ -98,16 +103,16 @@ public ApiPagingResultResponse getPostsListCreatedAt(Long // 회고글 상세페이지 @Transactional(isolation = Isolation.READ_COMMITTED) - public ApiIsResultResponse findPostContents(Long postIdx, Long userIdx){ + public Post findPostContents(Long postIdx, Long userIdx){ Post post = postRepository.findById(postIdx) .orElseThrow(() -> new EntityNullException(ErrorInfo.POST_NULL)); - post.updateview(post.getView()); // 조회수 증가 + // 조회수 증가 + post.updateview(post.getView()); + // 최근 읽은 글에 추가 if(userIdx != 0L){ - listService.saveRecentReadPosts(userIdx, postIdx); // 최근 읽은 글에 추가 + listService.saveRecentReadPosts(userIdx, postIdx); } - return new ApiIsResultResponse<>(isWriter(post.getUser().getUserIdx(),userIdx), - isScrap(post, userIdx), - postMapper.postToDetailResponse(post)); // 작성자 판단 + return post; } @@ -176,18 +181,13 @@ public Long updatePosts(Long userIdx,Long postIdx, PostDto.updateRequest request // 회고글 삭제 @Transactional - public boolean deletePosts(Long userIdx,Long postIdx) { + public void deletePosts(Long userIdx,Long postIdx) { Post post = postRepository.findById(postIdx) .orElseThrow(() -> new EntityNullException(ErrorInfo.POST_NULL)); - if (isWriter(post.getUser().getUserIdx(), userIdx)){ + if (!isWriter(post.getUser().getUserIdx(), userIdx)) throw new EntityNullException(ErrorInfo.POST_NULL); + else{ postRepository.deleteById(postIdx); -// if (listService.isPostsExist(userIdx, postIdx)) { -// // ** redis에 있는 모든...어쩌구.... -// listService.deleteRedisPost(userIdx, postIdx); // redis 에서도 삭제 -// } - return true; } - return false; } @@ -212,13 +212,13 @@ public boolean isView(User user, Long cursorId){ // 작성자 판별 - private boolean isWriter(Long postUserIdx, Long userIdx){ + public boolean isWriter(Long postUserIdx, Long userIdx){ if (userIdx == 0L) return false; return postUserIdx.equals(userIdx); } // 스크랩 여부 판별 -> 리팩토링 필요 - private boolean isScrap(Post post, Long userIdx){ + public boolean isScrap(Post post, Long userIdx){ return likeRepository.findByPostAndUserUserIdx(post, userIdx).isPresent(); } @@ -227,4 +227,8 @@ private List compareList(List newList, List compareList) return newList.stream().filter(x -> !compareList.contains(x)).collect(Collectors.toList()); } + //포스트 존재 여부 + public boolean existsByPostIdx(Long postIdx){ + return postRepository.existsByPostIdx(postIdx); + } } diff --git a/src/main/java/com/yapp18/retrospect/service/SearchService.java b/src/main/java/com/yapp18/retrospect/service/SearchService.java index 39ea944..889763b 100644 --- a/src/main/java/com/yapp18/retrospect/service/SearchService.java +++ b/src/main/java/com/yapp18/retrospect/service/SearchService.java @@ -1,9 +1,11 @@ package com.yapp18.retrospect.service; +import com.yapp18.retrospect.config.ErrorInfo; import com.yapp18.retrospect.domain.post.Post; import com.yapp18.retrospect.domain.post.PostQueryRepository; import com.yapp18.retrospect.domain.post.PostRepository; import com.yapp18.retrospect.mapper.PostMapper; +import com.yapp18.retrospect.web.advice.EntityNullException; import com.yapp18.retrospect.web.dto.ApiPagingResultResponse; import com.yapp18.retrospect.web.dto.PostDto; import com.yapp18.retrospect.web.dto.SearchDto; @@ -30,15 +32,20 @@ public ApiPagingResultResponse searchByType(SearchDto sear // 카테고리 검색 시 List result; if (searchDto.getType().equals("category") && searchDto.getKeyword() == null){ // 검색타입이 카테고리고 키워드가 없음. - result = getPostCategory(searchDto.getPage(), pageable, searchDto.getQuery()) // cursorId, 페이지 정보, 쿼리 넘김(카테고리) - .stream().map(post->postMapper.postToListResponse(post, userIdx)) + List posts = getPostCategory(searchDto.getPage(), pageable, searchDto.getQuery()) ;// cursorId, 페이지 정보, 쿼리 넘김(카테고리) + if (posts.isEmpty()) throw new EntityNullException(ErrorInfo.CONDITION_NULL); + + result = posts.stream().map(post->postMapper.postToListResponse(post, userIdx)) .collect(Collectors.toList()); } else{ // 통합 검색 시 - result = findAllByType(searchDto.getType(), searchDto.getQuery(), searchDto.getKeyword(), searchDto.getPage(),pageable) - .stream().map(post->postMapper.postToListResponse(post, userIdx)) + List posts = findAllByType(searchDto.getType(), searchDto.getQuery(), searchDto.getKeyword(), searchDto.getPage(),pageable); + if (posts.isEmpty()) throw new EntityNullException(ErrorInfo.CONDITION_NULL); + + result = posts.stream().map(post->postMapper.postToListResponse(post, userIdx)) .collect(Collectors.toList()); } + Long lastIdx = result.isEmpty() ? null : result.get(result.size()-1).getPostIdx(); return new ApiPagingResultResponse<>(isNext(searchDto, pageable, lastIdx), result); } @@ -47,7 +54,10 @@ public ApiPagingResultResponse searchByType(SearchDto sear // 해시태그로 검색 @Transactional(readOnly = true) public ApiPagingResultResponse getPostsByHashTag(String tag, Long cursorId, Pageable pageable, Long userIdx){ - List result = findAllByTag(cursorId, pageable, tag).stream() + List posts = findAllByTag(cursorId, pageable, tag); + if (posts.isEmpty()) throw new EntityNullException(ErrorInfo.CONDITION_NULL); + + List result= posts.stream() .map(post->postMapper.postToListResponse(post, userIdx)) .collect(Collectors.toList()); Long lastIdx = result.isEmpty() ? null : result.get(result.size()-1).getPostIdx(); @@ -55,7 +65,6 @@ public ApiPagingResultResponse getPostsByHashTag(String ta } - // 통합 검색 분기처리 private List findAllByType(String type, String query, String keyword, Long cursorId, Pageable page){ return cursorId == null || cursorId == 0 ? diff --git a/src/main/java/com/yapp18/retrospect/service/UserService.java b/src/main/java/com/yapp18/retrospect/service/UserService.java index db51127..263eb5e 100644 --- a/src/main/java/com/yapp18/retrospect/service/UserService.java +++ b/src/main/java/com/yapp18/retrospect/service/UserService.java @@ -15,18 +15,16 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; @RequiredArgsConstructor @Service public class UserService { - private final UserMapper mapper; + private final UserMapper userMapper; private final UserRepository userRepository; private final ImageService imageService; private final AppProperties appProperties; - private final UserMapper userMapper; @Value("${app.values.s3ProfileImagePathSuffix}") public String s3ProfileImagePathSuffix; @@ -54,7 +52,7 @@ public User registerNewUser(String registrationId, OAuth2UserInfo oAuth2UserInfo @Transactional(readOnly = true) public UserDto.ProfileResponse getUserProfiles(Long userIdx, Long extractedIdx) { return userRepository.findByUserIdx(userIdx) - .map(user -> mapper.userToProfileResponse(user, user.getUserIdx().equals(extractedIdx))) + .map(user -> userMapper.userToProfileResponse(user, user.getUserIdx().equals(extractedIdx))) .orElseThrow(() -> new EntityNullException(ErrorInfo.USER_NULL)); } @@ -67,11 +65,11 @@ public UserDto.ProfileResponse updateUserProfiles(Long userIdx, UserDto.UpdateRe List list = Arrays.asList(request.getProfile()); imageService.deleteImageList(list, userIdx, s3ProfileImagePathSuffix); // list에 없는 s3 가비지 데이터를 추출하여 삭제 } - return existingUser.updateProfile(request.getProfile(), request.getName(), request.getNickname(), request.getJob(), request.getIntro()); + return existingUser.updateProfile(request.getName(), request.getNickname(), request.getProfile(), request.getJob(), request.getIntro()); }) .orElseThrow(() -> new EntityNullException(ErrorInfo.USER_NULL)); userRepository.save(user); - return mapper.userToProfileResponse(user); + return userMapper.userToProfileResponse(user); } @Transactional @@ -91,4 +89,9 @@ public User findByUserEmail(String email){ return userRepository.findByEmail(email) .orElseThrow(() -> new EntityNullException(ErrorInfo.USER_NULL)); } + + + public Long getUserInfoFromToken(User user){ + return (user != null)? user.getUserIdx(): 0L; + } } diff --git a/src/main/java/com/yapp18/retrospect/web/advice/ControllerAdvice.java b/src/main/java/com/yapp18/retrospect/web/advice/ControllerAdvice.java index ae05478..b08e3fd 100644 --- a/src/main/java/com/yapp18/retrospect/web/advice/ControllerAdvice.java +++ b/src/main/java/com/yapp18/retrospect/web/advice/ControllerAdvice.java @@ -1,5 +1,6 @@ package com.yapp18.retrospect.web.advice; +import com.yapp18.retrospect.web.dto.ApiDefaultResponse; import com.yapp18.retrospect.web.dto.ErrorDefaultResponse; import com.yapp18.retrospect.web.dto.ErrorDto; import org.springframework.http.HttpStatus; @@ -79,7 +80,7 @@ public ResponseEntity> restExceptionHandler(RestException e) // @ExceptionHandler(EntityNullException.class) // public ResponseEntity entityNullExceptionHandler(EntityNullException e) { -// return new ResponseEntity<>(ApiDefaultResponse.res(404, e.getMessage()), e.getStatus()); +// return new ResponseEntity<>(ApiDefaultResponse.res(404, e.getMessage()), e.getCode()); // } // @ResponseStatus(HttpStatus.BAD_REQUEST) diff --git a/src/main/java/com/yapp18/retrospect/web/controller/CommentController.java b/src/main/java/com/yapp18/retrospect/web/controller/CommentController.java index 1b4813e..7604dcb 100644 --- a/src/main/java/com/yapp18/retrospect/web/controller/CommentController.java +++ b/src/main/java/com/yapp18/retrospect/web/controller/CommentController.java @@ -1,21 +1,14 @@ package com.yapp18.retrospect.web.controller; import com.yapp18.retrospect.annotation.CurrentUser; -import com.yapp18.retrospect.config.ErrorInfo; import com.yapp18.retrospect.config.ResponseMessage; import com.yapp18.retrospect.domain.comment.Comment; -import com.yapp18.retrospect.domain.comment.CommentRepository; import com.yapp18.retrospect.domain.post.Post; import com.yapp18.retrospect.domain.user.User; -import com.yapp18.retrospect.domain.user.UserRepository; import com.yapp18.retrospect.mapper.CommentMapper; import com.yapp18.retrospect.service.CommentService; -import com.yapp18.retrospect.service.PostService; -import com.yapp18.retrospect.service.TokenService; -import com.yapp18.retrospect.web.advice.EntityNullException; import com.yapp18.retrospect.web.dto.ApiDefaultResponse; import com.yapp18.retrospect.web.dto.CommentDto; -import com.yapp18.retrospect.web.dto.UserDto; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; @@ -25,7 +18,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletRequest; import java.util.List; import java.util.stream.Collectors; @@ -53,16 +45,6 @@ public ResponseEntity inputComments(@CurrentUser User user, ); } - @ApiOperation(value = "comment", notes = "[댓글] 댓글 상세보기") - @GetMapping("/{commentIdx}") - public ResponseEntity getCommentsById(@ApiParam(value = "상세보기 comment_idx", required = true, example = "3") - @PathVariable(value = "commentIdx") Long commentIdx) { - return ResponseEntity.status(HttpStatus.OK).body( - ApiDefaultResponse.res(200, ResponseMessage.COMMENT_DETAIL.getResponseMessage(), - commentMapper.toDto(commentService.getCommmentsByIdx(commentIdx))) - ); - } - @ApiOperation(value = "comment", notes = "[댓글] 댓글 수정") @PatchMapping("/{commentIdx}") public ResponseEntity updateComments(@CurrentUser User user, @@ -94,11 +76,11 @@ public ResponseEntity deleteComments(@CurrentUser User user, public ResponseEntity getCommentsByPostIdx(@CurrentUser User user, @ApiParam(value = "회고글 post_idx", required = true, example = "20") @RequestParam(value = "postIdx") Long postIdx, - @RequestParam(value = "cursorIdx(디폴트 0, 페이징 하고 싶은 맨 마지막 postIdx 입력)", defaultValue = "0") Long cursorIdx, + @RequestParam(value = "page", defaultValue = "0") Long page, @RequestParam(value = "pageSize") Integer pageSize){ if (pageSize == null) pageSize = DEFAULT_SIZE; - List result = commentService.getCommmentsListByPostIdx(postIdx, PageRequest.of(page, pageSize)) + List result = commentService.getCommmentsListByPostIdx(postIdx, PageRequest.of(page.intValue(), pageSize)) .stream() .map(comment -> commentMapper.toDto(comment, user)) .collect(Collectors.toList()); diff --git a/src/main/java/com/yapp18/retrospect/web/controller/PostController.java b/src/main/java/com/yapp18/retrospect/web/controller/PostController.java index 133aaea..a554e67 100644 --- a/src/main/java/com/yapp18/retrospect/web/controller/PostController.java +++ b/src/main/java/com/yapp18/retrospect/web/controller/PostController.java @@ -1,10 +1,16 @@ package com.yapp18.retrospect.web.controller; +import com.yapp18.retrospect.annotation.CurrentUser; import com.yapp18.retrospect.config.ResponseMessage; +import com.yapp18.retrospect.domain.post.Post; +import com.yapp18.retrospect.domain.user.User; +import com.yapp18.retrospect.mapper.PostMapper; import com.yapp18.retrospect.service.PostService; import com.yapp18.retrospect.service.TokenService; +import com.yapp18.retrospect.service.UserService; import com.yapp18.retrospect.web.dto.ApiDefaultResponse; +import com.yapp18.retrospect.web.dto.ApiIsResultResponse; import com.yapp18.retrospect.web.dto.PostDto; import io.swagger.annotations.*; import lombok.RequiredArgsConstructor; @@ -24,30 +30,22 @@ public class PostController { private final PostService postService; private final TokenService tokenService; + private final UserService userService; + private final PostMapper postMapper; private static final int DEFAULT_SIZE = 20; -// @ApiOperation(value = "main", notes = "[메인] 회고글 목록 조회, 최신순") // api tag, 설명 -// @GetMapping("/lists/new") -// public ResponseEntity getMainPosts(@ApiParam(value = "현재 페이지 마지막 post_idx", required = true, example = "20") -// HttpServletRequest request, -// @RequestParam(value = "page", defaultValue = "0") Long page, -// @RequestParam(value = "pageSize",defaultValue = "20") Integer pageSize){ -// if (pageSize == null) pageSize = DEFAULT_SIZE; -// Long userIdx = (tokenService.getTokenFromRequest(request) != null) ? tokenService.getUserIdx(tokenService.getTokenFromRequest(request)) : 0L; -// return new ResponseEntity<>(ApiDefaultResponse.res(200,ResponseMessage.POST_FIND_RECENT.getResponseMessage(), -// postService.getPostsListRecent(page, PageRequest.of(0, pageSize), userIdx)), HttpStatus.OK); -// } - @ApiOperation(value = "main", notes = "[메인] 회고글 목록 조회, 누적조회순") @GetMapping("/lists") public ResponseEntity getMainPostsOrderByView(@ApiParam(value = "현재 페이지 마지막 post_idx", required = true, example = "20") - HttpServletRequest request, - @RequestParam(value = "page", defaultValue = "0") Long page, - @RequestParam(value = "pageSize") Integer pageSize){ + @CurrentUser User user, + @RequestParam(value = "page", defaultValue = "0") Long page, + @RequestParam(value = "pageSize") Integer pageSize){ if (pageSize == null) pageSize = DEFAULT_SIZE; - Long userIdx = (tokenService.getTokenFromRequest(request) != null) ? tokenService.getUserIdx(tokenService.getTokenFromRequest(request)) : 0L; - return new ResponseEntity<>(ApiDefaultResponse.res(200,ResponseMessage.POST_FIND_VIEW.getResponseMessage(), - postService.getPostsListView(page, PageRequest.of(0, pageSize), userIdx)), HttpStatus.OK); + + return ResponseEntity.status(HttpStatus.OK).body( + ApiDefaultResponse.res(200, + ResponseMessage.POST_FIND_VIEW.getResponseMessage(), + postService.getPostsListView(page, PageRequest.of(0,pageSize), userService.getUserInfoFromToken(user)))); } @ApiOperation(value = "main", notes = "[프로필] 유저 회고글 목록 조회, 생성일자순") @@ -57,68 +55,60 @@ public ResponseEntity getPostsByUserIdxOrderByCreatedAtDesc(@ApiParam(va @RequestParam(value = "page", defaultValue = "0") Long page, @RequestParam(value = "pageSize") Integer pageSize){ if (pageSize == null) pageSize = DEFAULT_SIZE; - return new ResponseEntity<>(ApiDefaultResponse.res(200, - ResponseMessage.POST_FIND_CREATED.getResponseMessage(), - postService.getPostsListCreatedAt(page, userIdx, PageRequest.of(0, pageSize))), HttpStatus.OK); + return ResponseEntity.status(HttpStatus.OK).body( + ApiDefaultResponse.res(200, ResponseMessage.POST_FIND_CREATED.getResponseMessage(), + postService.getPostsListCreatedAt(page, userIdx, PageRequest.of(0, pageSize)))); } @ApiOperation(value = "detail", notes = "[상세] 회고글 상세보기") @GetMapping("/{postIdx}") - public ResponseEntity findPostsContentById(HttpServletRequest request, + public ResponseEntity findPostsContentById(@CurrentUser User user, @ApiParam(value = "상세보기 post_idx", required = true, example = "3") @PathVariable(value = "postIdx") Long postIdx) { - Long userIdx = (tokenService.getTokenFromRequest(request) != null) ? tokenService.getUserIdx(tokenService.getTokenFromRequest(request)) : 0L; - return new ResponseEntity<>(ApiDefaultResponse.res(200,ResponseMessage.POST_DETAIL.getResponseMessage(), - postService.findPostContents(postIdx, userIdx)), HttpStatus.OK); - } + Long userIdx = userService.getUserInfoFromToken(user); + Post post = postService.findPostContents(postIdx, userIdx); + + return ResponseEntity.status(HttpStatus.OK).body( + new ApiIsResultResponse<>(postService.isWriter(post.getUser().getUserIdx(), userIdx), + postService.isScrap(post, userIdx), + postMapper.postToDetailResponse(post)) + ); + } @ApiOperation(value = "main", notes = "[메인]회고글 저장하기") @PostMapping("") - public ResponseEntity inputPosts(HttpServletRequest request, + public ResponseEntity inputPosts(@CurrentUser User user, @RequestBody PostDto.saveResponse saveResponse){ - Long postIdx = postService.inputPosts(saveResponse, tokenService.getUserIdx(tokenService.getTokenFromRequest(request))); - return new ResponseEntity<>(ApiDefaultResponse.res(200,ResponseMessage.POST_SAVE.getResponseMessage(), postIdx), HttpStatus.OK); + Long userIdx = userService.getUserInfoFromToken(user); + Long postIdx = postService.inputPosts(saveResponse, userIdx); + return ResponseEntity.status(HttpStatus.OK).body( + ApiDefaultResponse.res(200, ResponseMessage.POST_SAVE.getResponseMessage(), postIdx) + ); } @ApiOperation(value = "mypage", notes = "[마이페이지]회고글 수정하기") @PutMapping("/{postIdx}") - public ResponseEntity updatePosts(HttpServletRequest request, + public ResponseEntity updatePosts(@CurrentUser User user, @ApiParam(value = "회고글 post_idx", required = true, example = "1") @PathVariable(value = "postIdx") Long postIdx, @RequestBody PostDto.updateRequest requestDto){ - Long post = postService.updatePosts(tokenService.getUserIdx(tokenService.getTokenFromRequest(request)), postIdx, requestDto); - return new ResponseEntity<>(ApiDefaultResponse.res(200,ResponseMessage.POST_UPDATE.getResponseMessage(),post),HttpStatus.OK); + Long userIdx = userService.getUserInfoFromToken(user); + Long post = postService.updatePosts(userIdx, postIdx, requestDto); + return ResponseEntity.status(HttpStatus.OK).body( + ApiDefaultResponse.res(200, ResponseMessage.POST_UPDATE.getResponseMessage(), post) + ); } @ApiOperation(value = "mypage", notes = "[마이페이지]회고글 삭제하기") @DeleteMapping("/{postIdx}") - public ResponseEntity deletePosts(HttpServletRequest request, + public ResponseEntity deletePosts(@CurrentUser User user, @ApiParam(value = "회고글 post_idx", required = true, example = "1") @PathVariable(value = "postIdx") Long postIdx){ - boolean isPost = postService.deletePosts(tokenService.getUserIdx(tokenService.getTokenFromRequest(request)),postIdx); - if (!isPost){ - return new ResponseEntity<>(ApiDefaultResponse.res(400,"삭제할 idx 없음...", false),HttpStatus.BAD_REQUEST); - } - return new ResponseEntity<>(ApiDefaultResponse.res(200, ResponseMessage.POST_DELETE.getResponseMessage(), true),HttpStatus.OK); + postService.deletePosts(userService.getUserInfoFromToken(user),postIdx); + return ResponseEntity.status(HttpStatus.OK).body( + ApiDefaultResponse.res(200, ResponseMessage.POST_DELETE.getResponseMessage()) + ); } - - // @ApiOperation(value = "main", notes = "[메인] 카테고리 필터링") -// @GetMapping("/lists/category") -// public ResponseEntity findPostsByCategory(HttpServletRequest request, -// @ApiParam(value = "카테고리", required = true, example = "design") -// @RequestParam(value = "query") String query, -// @ApiParam(value = "page", required = true, example = "0") -// @RequestParam(value = "page") Long page, -// @ApiParam(value = "pageSize", required = true, example = "20") -// @RequestParam(value = "pageSize") Integer pageSize -// ){ -// if (pageSize == null) pageSize = DEFAULT_SIZE; -// System.out.println("_---->" + request.getQueryString()); -// System.out.println(query); -// Long userIdx = (tokenService.getTokenFromRequest(request) != null) ? tokenService.getUserIdx(tokenService.getTokenFromRequest(request)) : 0L; -// return new ResponseEntity<>(ApiDefaultResponse.res(200,ResponseMessage.POST_FIND_CATEGORY.getResponseMessage(), -// postService.getPostsByCategory(query, page, PageRequest.of(0,pageSize), userIdx)), HttpStatus.OK); -// } } diff --git a/src/main/resources/application-key.yaml b/src/main/resources/application-key.yaml new file mode 100644 index 0000000..5711bb0 --- /dev/null +++ b/src/main/resources/application-key.yaml @@ -0,0 +1,2 @@ +secret: + access: accessTokenSecret \ No newline at end of file diff --git a/src/test/java/com/yapp18/retrospect/annotation/RetrospectDataTest.java b/src/test/java/com/yapp18/retrospect/annotation/RetrospectDataTest.java new file mode 100644 index 0000000..d8f7d80 --- /dev/null +++ b/src/test/java/com/yapp18/retrospect/annotation/RetrospectDataTest.java @@ -0,0 +1,29 @@ +package com.yapp18.retrospect.annotation; + +import com.github.springtestdbunit.TransactionDbUnitTestExecutionListener; +import com.github.springtestdbunit.annotation.DbUnitConfiguration; +import com.yapp18.retrospect.config.DBUnitConfig; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) // 어노테이션을 작성할 곳, @Target(ElementType.FIELD)로 지정해주면, 필드에만 어노테이션을 달 수 있습니다. +@Retention(RetentionPolicy.RUNTIME) // 어노테이션의 지속 시간을 정합니다. 이 어노테이션은 런타임시에도 .class 파일에 존재 합니다. 커스텀 어노테이션을 만들 때 주로 사용합니다. Reflection 사용 가능이 가능합니다. +@Import(DBUnitConfig.class) // https://younicode.tistory.com/entry/Spring-boot%EC%97%90%EC%84%9C-DBUnit-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0 +@DataJpaTest // https://webcoding-start.tistory.com/20, https://howtodoinjava.com/spring-boot2/testing/datajpatest-annotation/ +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) // Replace.NONE로 설정하면 @ActiveProfiles에 설정한 프로파일 환경값에 따라 데이터 소스가 적용됩니다. +// TestContextManager에 어떤 TestExecutionListener들이 등록되어야 하는지 설정할 수 있게 지원합니다. +@ContextConfiguration +@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, // 스프링 테스트 환경에서 일반적으로 사용되는 의존성 주입 (DI) 리스너입니다. 테스트 인스턴스에 대한 의존성 주입 (DI) 을 제공합니다. + TransactionDbUnitTestExecutionListener.class }) +@DbUnitConfiguration(databaseConnection = "dbUnitDatabaseConnection") +public @interface RetrospectDataTest { +} diff --git a/src/test/java/com/yapp18/retrospect/api/annotation/WithMockRetrospectUser.java b/src/test/java/com/yapp18/retrospect/annotation/WithMockRetrospectUser.java similarity index 72% rename from src/test/java/com/yapp18/retrospect/api/annotation/WithMockRetrospectUser.java rename to src/test/java/com/yapp18/retrospect/annotation/WithMockRetrospectUser.java index b558665..9fe3bcd 100644 --- a/src/test/java/com/yapp18/retrospect/api/annotation/WithMockRetrospectUser.java +++ b/src/test/java/com/yapp18/retrospect/annotation/WithMockRetrospectUser.java @@ -1,6 +1,6 @@ -package com.yapp18.retrospect.api.annotation; +package com.yapp18.retrospect.annotation; -import com.yapp18.retrospect.api.config.WithMockUserSecurityContextFactory; +import com.yapp18.retrospect.config.WithMockUserSecurityContextFactory; import org.springframework.security.test.context.support.WithSecurityContext; import java.lang.annotation.Retention; diff --git a/src/test/java/com/yapp18/retrospect/api/oauth2/OAuth2ControllerTest.java b/src/test/java/com/yapp18/retrospect/api/oauth2/OAuth2ControllerTest.java deleted file mode 100644 index 9a7c44b..0000000 --- a/src/test/java/com/yapp18/retrospect/api/oauth2/OAuth2ControllerTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.yapp18.retrospect.api.oauth2; - -import com.yapp18.retrospect.domain.user.Role; -import com.yapp18.retrospect.domain.user.User; -import com.yapp18.retrospect.security.oauth2.AuthProvider; -import com.yapp18.retrospect.service.UserService; -import com.yapp18.retrospect.web.AbstractControllerTest; -import org.springframework.boot.test.mock.mockito.MockBean; - -public class OAuth2ControllerTest extends AbstractControllerTest { - private final User newUser = User.builder() - .email("ybell1028@daum.net") - .name("real-name") - .nickname("Walkman") - .profile("profile-url") - .provider(AuthProvider.kakao) - .providerId("12345") - .role(Role.MEMBER) - .job("job") - .intro("intro") - .build(); - - @MockBean - UserService userService; -} diff --git a/src/test/java/com/yapp18/retrospect/common/EntityCreator.java b/src/test/java/com/yapp18/retrospect/common/EntityCreator.java index 491c7f1..9dd10bc 100644 --- a/src/test/java/com/yapp18/retrospect/common/EntityCreator.java +++ b/src/test/java/com/yapp18/retrospect/common/EntityCreator.java @@ -1,6 +1,7 @@ package com.yapp18.retrospect.common; import com.yapp18.retrospect.domain.comment.Comment; +import com.yapp18.retrospect.domain.like.Like; import com.yapp18.retrospect.domain.post.Post; import com.yapp18.retrospect.domain.template.Template; import com.yapp18.retrospect.domain.user.Role; @@ -14,6 +15,7 @@ public class EntityCreator { private static final Long POST_IDX = 1L; private static final Long COMMENT_IDX = 1L; private static final Long TEMPLATE_IDX = 1L; + private static final Long LIKE_IDX = 1L; public static User createUserEntity(){ User user = User.builder() @@ -21,9 +23,9 @@ public static User createUserEntity(){ .email("test@example.com") .name("테스트이름") .nickname("테스트닉네임") - .profile("profile-url") + .profile("프로필URL") .provider(AuthProvider.kakao) - .providerId("12345") + .providerId("1") .role(Role.MEMBER) .job("테스트직업") .intro("테스트자기소개") @@ -77,4 +79,17 @@ public static Comment createCommentEntity(){ return comment; } + + public static Like createLikeEntity(){ + Like like = Like.builder() + .likeIdx(LIKE_IDX) + .post(createPostEntity()) + .user(createUserEntity()) + .build(); + + like.setCreatedAt(LocalDateTime.of(2021, 10, 28, 12, 0, 0)); + like.setModifiedAt(LocalDateTime.of(2021, 10, 28, 12, 0, 0)); + + return like; + } } diff --git a/src/test/java/com/yapp18/retrospect/config/DBUnitConfig.java b/src/test/java/com/yapp18/retrospect/config/DBUnitConfig.java new file mode 100644 index 0000000..3b650fb --- /dev/null +++ b/src/test/java/com/yapp18/retrospect/config/DBUnitConfig.java @@ -0,0 +1,28 @@ +package com.yapp18.retrospect.config; + +import com.github.springtestdbunit.bean.DatabaseConfigBean; +import com.github.springtestdbunit.bean.DatabaseDataSourceConnectionFactoryBean; +import org.dbunit.ext.h2.H2DataTypeFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +@Configuration +public class DBUnitConfig { + @Bean + public DatabaseConfigBean dbUnitDatabaseConfig() { + DatabaseConfigBean config = new DatabaseConfigBean(); + config.setAllowEmptyFields(true); + config.setDatatypeFactory(new H2DataTypeFactory()); + return config; + } + + @Bean + public DatabaseDataSourceConnectionFactoryBean dbUnitDatabaseConnection(DataSource dataSource) { + DatabaseDataSourceConnectionFactoryBean dbUnitDatabaseConnection = new DatabaseDataSourceConnectionFactoryBean(); + dbUnitDatabaseConnection.setDataSource(dataSource); + dbUnitDatabaseConnection.setDatabaseConfig(dbUnitDatabaseConfig()); + return dbUnitDatabaseConnection; + } +} diff --git a/src/test/java/com/yapp18/retrospect/api/config/WithMockUserSecurityContextFactory.java b/src/test/java/com/yapp18/retrospect/config/WithMockUserSecurityContextFactory.java similarity index 93% rename from src/test/java/com/yapp18/retrospect/api/config/WithMockUserSecurityContextFactory.java rename to src/test/java/com/yapp18/retrospect/config/WithMockUserSecurityContextFactory.java index ddeef28..1f2b23e 100644 --- a/src/test/java/com/yapp18/retrospect/api/config/WithMockUserSecurityContextFactory.java +++ b/src/test/java/com/yapp18/retrospect/config/WithMockUserSecurityContextFactory.java @@ -1,6 +1,6 @@ -package com.yapp18.retrospect.api.config; +package com.yapp18.retrospect.config; -import com.yapp18.retrospect.api.annotation.WithMockRetrospectUser; +import com.yapp18.retrospect.annotation.WithMockRetrospectUser; import com.yapp18.retrospect.domain.user.Role; import com.yapp18.retrospect.domain.user.User; import com.yapp18.retrospect.security.UserPrincipal; diff --git a/src/test/java/com/yapp18/retrospect/domain/comment/CommentRepositoryTest.java b/src/test/java/com/yapp18/retrospect/domain/comment/CommentRepositoryTest.java new file mode 100644 index 0000000..fe71d1d --- /dev/null +++ b/src/test/java/com/yapp18/retrospect/domain/comment/CommentRepositoryTest.java @@ -0,0 +1,97 @@ +package com.yapp18.retrospect.domain.comment; + +import com.github.springtestdbunit.annotation.DatabaseSetup; +import com.github.springtestdbunit.annotation.ExpectedDatabase; +import com.github.springtestdbunit.assertion.DatabaseAssertionMode; +import com.yapp18.retrospect.annotation.RetrospectDataTest; +import com.yapp18.retrospect.common.EntityCreator; +import com.yapp18.retrospect.domain.post.Post; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; + +import javax.persistence.EntityManager; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@RetrospectDataTest +public class CommentRepositoryTest { + @Autowired + CommentRepository commentRepository; + + @Autowired + EntityManager entityManager; + + Post post = EntityCreator.createPostEntity(); + + @BeforeEach + public void init(){ + commentRepository.restartIdxSequence(); // userIdx sequence 초기화 + } + + @Test + @DatabaseSetup({ + "classpath:dbunit/User/사용자_한명_존재.xml", + "classpath:dbunit/Post/회고글_한개_존재.xml", + }) + @ExpectedDatabase(value = "classpath:dbunit/Comment/댓글_한개_존재.xml", + assertionMode = DatabaseAssertionMode.NON_STRICT) + public void 댓글_등록() { + commentRepository.save(EntityCreator.createCommentEntity()); + } + + @Test + @DatabaseSetup({ + "classpath:dbunit/User/사용자_한명_존재.xml", + "classpath:dbunit/Post/회고글_한개_존재.xml", + "classpath:dbunit/Comment/댓글_두개_존재.xml" + }) + public void 회고글에_달린_댓글_리스트_조회() { + List commentList = commentRepository.findAllByPostIdx(1L, PageRequest.of(0, 2)); + + assertThat(commentList.size()).isEqualTo(2); + assertThat(commentList.get(0).getCommentIdx()).isEqualTo(1); + assertThat(commentList.get(0).getComments()).isEqualTo("댓글내용1"); + assertThat(commentList.get(1).getCommentIdx()).isEqualTo(2); + assertThat(commentList.get(1).getComments()).isEqualTo("댓글내용2"); + } + + @Test + @DatabaseSetup({ + "classpath:dbunit/User/사용자_한명_존재.xml", + "classpath:dbunit/Post/회고글_한개_존재.xml", + "classpath:dbunit/Comment/댓글_두개_존재.xml" + }) + public void 회고글에_달린_댓글_커서_조회() { + Long count = commentRepository.countCommentByPost(post); + + assertThat(count).isEqualTo(2); + } + + @Test + @DatabaseSetup({ + "classpath:dbunit/User/사용자_한명_존재.xml", + "classpath:dbunit/Post/회고글_한개_존재.xml", + "classpath:dbunit/Comment/댓글_네개_존재.xml" + }) +// public void 회고글에_달린_댓글_커서_페이징_True() { + public void 마지막_댓글_다음_페이지_있는지_True() { + boolean exist = commentRepository.existsByCommentIdxGreaterThanAndPost(2L, post); + + assertThat(exist).isEqualTo(true); + } + + @Test + @DatabaseSetup({ + "classpath:dbunit/User/사용자_한명_존재.xml", + "classpath:dbunit/Post/회고글_한개_존재.xml", + "classpath:dbunit/Comment/댓글_네개_존재.xml" + }) + public void 마지막_댓글_다음_페이지_있는지_False() { + boolean exist = commentRepository.existsByCommentIdxGreaterThanAndPost(4L, post); + + assertThat(exist).isEqualTo(false); + } +} \ No newline at end of file diff --git a/src/test/java/com/yapp18/retrospect/domain/like/LikeRepositoryTest.java b/src/test/java/com/yapp18/retrospect/domain/like/LikeRepositoryTest.java index 6c35b88..eff1e06 100644 --- a/src/test/java/com/yapp18/retrospect/domain/like/LikeRepositoryTest.java +++ b/src/test/java/com/yapp18/retrospect/domain/like/LikeRepositoryTest.java @@ -1,106 +1,126 @@ -//package com.yapp18.retrospect.domain.like; -// -//import com.yapp18.retrospect.domain.post.Post; -//import com.yapp18.retrospect.domain.template.Template; -//import com.yapp18.retrospect.domain.user.User; -//import org.junit.jupiter.api.AfterEach; -//import org.junit.jupiter.api.Test; -//import org.junit.jupiter.api.extension.ExtendWith; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.boot.test.context.SpringBootTest; -//import org.springframework.test.context.junit.jupiter.SpringExtension; -// -//import java.util.List; -// -//import static org.assertj.core.api.Assertions.assertThat; -// -//@ExtendWith(SpringExtension.class) -//@SpringBootTest -//public class LikeRepositoryTest { -// @Autowired -// LikeRepository likeRepository; -// -// @AfterEach -// public void teardown() { -// likeRepository.deleteAll(); -// } -// -// String name_1 = "테스트 이름1"; -// String nickname_1 = "테스트 닉네임1"; -// String intro_1 = "테스트 자기소개1"; -// String email_1 = "test1@gmail.com"; -// String picture_1 = null; -// String platform_1 = "google"; -// String job_1 = "개발자"; -// String access_token_1 = null; -// -// String name_2 = "테스트 이름2"; -// String nickname_2 = "테스트 닉네임2"; -// String intro_2 = "테스트 자기소개2"; -// String email_2 = "test2@naver.com"; -// String picture_2 = null; -// String platform_2 = "naver"; -// String job_2 = "기획자"; -// String access_token_2 = null; -// -// User user1 = User.builder() -// .name(name_1) -// .nickname(nickname_1) -// .intro(intro_1) -// .email(email_1) -// .picture(picture_1) -// .platform(platform_1) -// .job(job_1) -// .build(); -// -// -// User user2 = User.builder() -// .name(name_2) -// .nickname(nickname_2) -// .intro(intro_2) -// .email(email_2) -// .picture(picture_2) -// .platform(platform_2) -// .job(job_2) -// .build(); -// -// String template_name = "4F"; -// String template_content = "..."; -// -// Template template = Template.builder() -// .template_name(template_name) -// .template(template_content) -// .user(user2) -// .build(); -// -// String category = "개발"; -// String title = "테스트 제목"; -// String content = "테스트 콘텐츠"; -// long view = 0; -// -// Post post = Post.builder() -// .category(category) -// .title(title) -// .contents(content) -// .view(view) -// .user(user2) -// .template(template) -// .build(); -// -// @Test -// public void 스크랩저장_불러오기() { -// likeRepository.save(Like.builder() -// .user(user1) -// .post(post) -// .build() -// ); -// -// List likeList = likeRepository.findAll(); -// -// Like like = likeList.get(0); -// -// assertThat(like.getUser().getName()).isEqualTo(name_1); -// assertThat(like.getPost().getUser().getName()).isEqualTo(name_2); -// assertThat(like.getPost().getTitle()).isEqualTo(title); -// } -//} +package com.yapp18.retrospect.domain.like; + +import com.github.springtestdbunit.annotation.DatabaseSetup; +import com.github.springtestdbunit.annotation.ExpectedDatabase; +import com.github.springtestdbunit.assertion.DatabaseAssertionMode; +import com.yapp18.retrospect.annotation.RetrospectDataTest; +import com.yapp18.retrospect.common.EntityCreator; +import com.yapp18.retrospect.domain.post.Post; +import com.yapp18.retrospect.domain.user.User; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; + +import javax.persistence.EntityManager; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@RetrospectDataTest +public class LikeRepositoryTest { + @Autowired + LikeRepository likeRepository; + + @Autowired + EntityManager entityManager; + + private final long USER_IDX = 1; + private final long LIKE_IDX = 1; + + @BeforeEach + public void init(){ + likeRepository.restartIdxSequence(); // likeIdx sequence 초기화 + } + + @Test + @DatabaseSetup({ + "classpath:dbunit/User/사용자_한명_존재.xml", + "classpath:dbunit/Post/회고글_한개_존재.xml", + }) + @ExpectedDatabase(value = "classpath:dbunit/Like/스크랩_한개_존재.xml", + assertionMode = DatabaseAssertionMode.NON_STRICT) + public void 스크랩_등록() { + likeRepository.save(EntityCreator.createLikeEntity()); + } + + @Test + @DatabaseSetup({ + "classpath:dbunit/User/사용자_두명_존재.xml", + "classpath:dbunit/Post/회고글_두개_존재.xml", + "classpath:dbunit/Like/스크랩_두개_존재.xml" + }) + public void 스크랩_조회_유저_별_생성일자_내림차순() { + User user = EntityCreator.createUserEntity(); + + List listList = likeRepository.findByUserOrderByCreatedAtDesc(user, PageRequest.of(0, 2)); + + assertThat(listList.size()).isEqualTo(2); + //내림차순이니까 2부터 + assertThat(listList.get(0).getLikeIdx()).isEqualTo(2L); + assertThat(listList.get(0).getPost().getPostIdx()).isEqualTo(2L); + assertThat(listList.get(1).getLikeIdx()).isEqualTo(1L); + assertThat(listList.get(1).getPost().getPostIdx()).isEqualTo(1L); + } + + @Test + @DatabaseSetup({ + "classpath:dbunit/User/사용자_두명_존재.xml", + "classpath:dbunit/Post/회고글_네개_존재.xml", + "classpath:dbunit/Like/스크랩_다섯개_존재.xml" + }) + public void 스크랩_커서_조회_유저_별_생성일자_내림차순() { + List listList = likeRepository.cursorFindByUserOrderByCreatedAtDesc(5L, USER_IDX, PageRequest.of(0, 2)); + + assertThat(listList.size()).isEqualTo(2); + //내림차순이니까 2부터 + assertThat(listList.get(0).getLikeIdx()).isEqualTo(2L); + assertThat(listList.get(0).getPost().getPostIdx()).isEqualTo(2L); + assertThat(listList.get(1).getLikeIdx()).isEqualTo(1L); + assertThat(listList.get(1).getPost().getPostIdx()).isEqualTo(1L); + } + + @Test + @DatabaseSetup({ + "classpath:dbunit/User/사용자_두명_존재.xml", + "classpath:dbunit/Post/회고글_네개_존재.xml", + "classpath:dbunit/Like/스크랩_다섯개_존재.xml" + }) + public void 스크랩_페이징_True() { + User user = EntityCreator.createUserEntity(); + + boolean result = likeRepository.existsByUserAndLikeIdxLessThan(user, 4L); + + assertThat(result).isEqualTo(true); + } + + @Test + @DatabaseSetup({ + "classpath:dbunit/User/사용자_두명_존재.xml", + "classpath:dbunit/Post/회고글_네개_존재.xml", + "classpath:dbunit/Like/스크랩_다섯개_존재.xml" + }) + public void 스크랩_페이징_False() { + User user = EntityCreator.createUserEntity(); + user.setUserIdx(2L); + + boolean result = likeRepository.existsByUserAndLikeIdxLessThan(user, 3L); + + assertThat(result).isEqualTo(false); + } + + @Test + @DatabaseSetup({ + "classpath:dbunit/User/사용자_한명_존재.xml", + "classpath:dbunit/Post/회고글_한개_존재.xml", + "classpath:dbunit/Like/스크랩_한개_존재.xml" + }) + @ExpectedDatabase(value = "classpath:dbunit/common/빈_테이블.xml", + assertionMode = DatabaseAssertionMode.NON_STRICT) + public void 스크랩_삭제_사용자_회고글() { + User user = EntityCreator.createUserEntity(); + Post post = EntityCreator.createPostEntity(); + + likeRepository.deleteByUserAndPost(user, post); + } +} diff --git a/src/test/java/com/yapp18/retrospect/domain/user/UserRepositoryTest.java b/src/test/java/com/yapp18/retrospect/domain/user/UserRepositoryTest.java new file mode 100644 index 0000000..84addd0 --- /dev/null +++ b/src/test/java/com/yapp18/retrospect/domain/user/UserRepositoryTest.java @@ -0,0 +1,122 @@ +package com.yapp18.retrospect.domain.user; + +import com.github.springtestdbunit.annotation.DatabaseSetup; +import com.github.springtestdbunit.annotation.ExpectedDatabase; +import com.github.springtestdbunit.assertion.DatabaseAssertionMode; +import com.yapp18.retrospect.annotation.RetrospectDataTest; +import com.yapp18.retrospect.common.EntityCreator; +import com.yapp18.retrospect.config.ErrorInfo; +import com.yapp18.retrospect.web.advice.EntityNullException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import javax.persistence.EntityManager; + +import static org.assertj.core.api.Assertions.assertThat; + +@RetrospectDataTest +public class UserRepositoryTest { + @Autowired + UserRepository userRepository; + + @Autowired + EntityManager entityManager; + + private final long USER_IDX = 1L; + + @BeforeEach + public void init(){ + userRepository.restartIdxSequence(); // userIdx sequence 초기화 + } + + @Test + @ExpectedDatabase(value = "classpath:dbunit/User/사용자_한명_존재.xml", + assertionMode = DatabaseAssertionMode.NON_STRICT) + public void 사용자_정보_등록() { + userRepository.save(EntityCreator.createUserEntity()); + } + + @Test + @DatabaseSetup(value = "classpath:dbunit/User/사용자_한명_존재.xml") + public void 사용자_정보_인덱스로_조회() { + User expected = EntityCreator.createUserEntity(); + + User user = userRepository.findByUserIdx(expected.getUserIdx()) + .orElseThrow(() -> new EntityNullException(ErrorInfo.USER_NULL)); + + assertThat(user.getUserIdx()).isEqualTo(expected.getUserIdx()); + assertThat(user.getEmail()).isEqualTo(expected.getEmail()); + assertThat(user.getName()).isEqualTo(expected.getName()); + assertThat(user.getNickname()).isEqualTo(expected.getNickname()); + assertThat(user.getProfile()).isEqualTo(expected.getProfile()); + assertThat(user.getJob()).isEqualTo(expected.getJob()); + assertThat(user.getIntro()).isEqualTo(expected.getIntro()); + assertThat(user.getProvider()).isEqualTo(expected.getProvider()); + assertThat(user.getProviderId()).isEqualTo(expected.getProviderId()); + assertThat(user.getRole()).isEqualTo(expected.getRole()); + } + + @Test + @DatabaseSetup(value = "classpath:dbunit/User/사용자_한명_존재.xml") + public void 사용자_정보_이메일로_조회() { + User expected = EntityCreator.createUserEntity(); + + User user = userRepository.findByEmail(expected.getEmail()) + .orElseThrow(() -> new EntityNullException(ErrorInfo.USER_NULL)); + + assertThat(user.getUserIdx()).isEqualTo(expected.getUserIdx()); + assertThat(user.getEmail()).isEqualTo(expected.getEmail()); + assertThat(user.getName()).isEqualTo(expected.getName()); + assertThat(user.getNickname()).isEqualTo(expected.getNickname()); + assertThat(user.getProfile()).isEqualTo(expected.getProfile()); + assertThat(user.getJob()).isEqualTo(expected.getJob()); + assertThat(user.getIntro()).isEqualTo(expected.getIntro()); + assertThat(user.getProvider()).isEqualTo(expected.getProvider()); + assertThat(user.getProviderId()).isEqualTo(expected.getProviderId()); + assertThat(user.getRole()).isEqualTo(expected.getRole()); + } + + @Test + @DatabaseSetup(value = "classpath:dbunit/User/사용자_한명_존재.xml") + public void 사용자_닉네임_조회_True() { + User expected = EntityCreator.createUserEntity(); + + boolean result = userRepository.existsByNickname(expected.getNickname()); + + assertThat(result).isEqualTo(true); + } + + @Test + @DatabaseSetup(value = "classpath:dbunit/User/사용자_한명_존재.xml") + public void 사용자_닉네임_조회_False() { + boolean result = userRepository.existsByNickname("존재하지않는닉네임"); + + assertThat(result).isEqualTo(false); + } + + @Test + @DatabaseSetup(value = "classpath:dbunit/User/사용자_한명_존재.xml") + @ExpectedDatabase(value = "classpath:dbunit/User/수정된_사용자_정보.xml", assertionMode = DatabaseAssertionMode.NON_STRICT) + + public void 사용자_정보_수정() { + User user = userRepository.findById(USER_IDX) + .orElseThrow(() -> new EntityNullException(ErrorInfo.USER_NULL)); + + user.updateProfile("수정된이름", "수정된닉네임", "수정된프로필URL", "수정된직업", "수정된자기소개"); + + userRepository.save(user); + + entityManager.flush(); // flush 연산을 통해 데이터베이스에 강제 반영 + } + + @Test + @DatabaseSetup(value = "classpath:dbunit/User/사용자_한명_존재.xml") + @ExpectedDatabase(value = "classpath:dbunit/common/빈_테이블.xml", assertionMode = DatabaseAssertionMode.NON_STRICT) + public void 사용자_정보_삭제() { + User user = userRepository.findById(USER_IDX) + .orElseThrow(() -> new EntityNullException(ErrorInfo.USER_NULL)); + + userRepository.delete(user); + } +} diff --git a/src/test/java/com/yapp18/retrospect/post/PostControllerTest.java b/src/test/java/com/yapp18/retrospect/post/PostControllerTest.java new file mode 100644 index 0000000..69a6c1c --- /dev/null +++ b/src/test/java/com/yapp18/retrospect/post/PostControllerTest.java @@ -0,0 +1,4 @@ +package com.yapp18.retrospect.post; + +public class PostControllerTest { +} diff --git a/src/test/java/com/yapp18/retrospect/post/PostCrudTest.java b/src/test/java/com/yapp18/retrospect/post/PostCrudTest.java deleted file mode 100644 index 8319662..0000000 --- a/src/test/java/com/yapp18/retrospect/post/PostCrudTest.java +++ /dev/null @@ -1,66 +0,0 @@ -//package com.yapp18.retrospect.post; -// -//import com.yapp18.retrospect.domain.post.Post; -//import com.yapp18.retrospect.domain.post.PostQueryRepository; -//import com.yapp18.retrospect.domain.post.PostRepository; -//import com.yapp18.retrospect.domain.template.Template; -//import com.yapp18.retrospect.domain.template.TemplateRepository; -//import com.yapp18.retrospect.domain.user.Role; -//import com.yapp18.retrospect.domain.user.User; -//import com.yapp18.retrospect.domain.user.UserRepository; -//import org.junit.jupiter.api.BeforeEach; -//import org.junit.jupiter.api.DisplayName; -//import org.junit.jupiter.api.Test; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -// -//import java.awt.font.OpenType; -//import java.util.Optional; -// -//@DataJpaTest -//public class PostCrudTest { -// -// @Autowired -// PostRepository postRepository; -// -// @Autowired -// UserRepository userRepository; -// -// @Autowired -// TemplateRepository templateRepository; -// -// @BeforeEach -// void setUp(){ -// // user 설정 -// User user1 = User.builder() -// .name("허정민").nickname("tape22").intro("자기소개.").job("백수") -// .email("test@naver.com").profile("profile_url") -// .provider("google").providerId("13453252535").role(Role.MEMBER).build(); -// // template 설정 -// Template template = Template.builder().template("템플릿").templateName("4F").build(); -// -// userRepository.save(user1); -// templateRepository.save(template); -// -// System.out.println(user1.getUserIdx()); -// System.out.println(template.getTemplateIdx()); -// -// } -// -// @Test -// @DisplayName("회고글 목록 조회: 최신순") -// void getRecentPostsList(){ -// // given -//// User user = userRepository.findById(1L); -//// Post post = Post.builder() -//// .category("design") -//// .contents("내용.......!!!!") -//// .title("테스트 1 제목") -//// .user(user) -//// .build(); -// -// // when -// // then -// System.out.println("test..."); -// } -//} diff --git a/src/test/java/com/yapp18/retrospect/post/PostServiceTest.java b/src/test/java/com/yapp18/retrospect/post/PostServiceTest.java new file mode 100644 index 0000000..9125525 --- /dev/null +++ b/src/test/java/com/yapp18/retrospect/post/PostServiceTest.java @@ -0,0 +1,71 @@ +package com.yapp18.retrospect.post; + +import com.yapp18.retrospect.common.EntityCreator; +import com.yapp18.retrospect.domain.post.Post; +import com.yapp18.retrospect.domain.post.PostQueryRepository; +import com.yapp18.retrospect.domain.post.PostRepository; +import com.yapp18.retrospect.domain.template.Template; +import com.yapp18.retrospect.domain.template.TemplateRepository; +import com.yapp18.retrospect.domain.user.Role; +import com.yapp18.retrospect.domain.user.User; +import com.yapp18.retrospect.domain.user.UserRepository; +import com.yapp18.retrospect.security.oauth2.AuthProvider; +import com.yapp18.retrospect.service.PostService; +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.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.data.domain.PageRequest; + +import java.awt.font.OpenType; +import java.util.List; +import java.util.Optional; + +//@DataJpaTest +@ExtendWith(MockitoExtension.class) +public class PostServiceTest { + + @InjectMocks + private PostService postService; + + @Mock + private PostRepository postRepository; + @Mock + private UserRepository userRepository; + @Mock + private TemplateRepository templateRepository; + + @BeforeEach + void setUp(){ +// // user 설정 +// User user1 = User.builder() +// .name("허정민").nickname("tape22").intro("자기소개.").job("백수") +// .email("test@naver.com").profile("profile_url") +// .provider(AuthProvider.google).providerId("13453252535").role(Role.MEMBER).build(); +// // template 설정 +// Template template = Template.builder().template("템플릿").templateName("4F").build(); +// +// userRepository.save(user1); +// templateRepository.save(template); +// +// System.out.println(user1.getUserIdx()); +// System.out.println(template.getTemplateIdx()); + } + + @Test + void 회고글이_없는_경우(){ + // list로 글 읽어오기 + List posts = postRepository.findAllByOrderByViewDesc(PageRequest.of(0,10)); + System.out.println(posts); + + // when + + // 없으면 빈 배열? 아니면 exception? + + } +} diff --git a/src/test/java/com/yapp18/retrospect/service/CommentServiceTest.java b/src/test/java/com/yapp18/retrospect/service/CommentServiceTest.java new file mode 100644 index 0000000..4f690c7 --- /dev/null +++ b/src/test/java/com/yapp18/retrospect/service/CommentServiceTest.java @@ -0,0 +1,235 @@ +package com.yapp18.retrospect.service; + +import com.yapp18.retrospect.common.EntityCreator; +import com.yapp18.retrospect.config.ErrorInfo; +import com.yapp18.retrospect.config.TokenErrorInfo; +import com.yapp18.retrospect.domain.comment.Comment; +import com.yapp18.retrospect.domain.comment.CommentRepository; +import com.yapp18.retrospect.web.advice.EntityNullException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +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 org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.security.access.AccessDeniedException; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doNothing; + +//여기서 Service를 테스트하기 위해서는 Repository 객체를 주입받아야 한다. +//그런데 이것을 주입받으려면 스프링을 띄울 수 밖에 없고, 테스트를 하는데 시간이 오래걸린다. +//무엇보다 데이터가 없는 경우 문제가 발생할 수 있다. +//그래서 Mock를 이용해 테스트를 하면 간단하다 + +@ExtendWith(MockitoExtension.class) +public class CommentServiceTest { + @InjectMocks + private CommentService commentService; + + @Mock + private CommentRepository commentRepository; + + @Mock + private PostService postService; + + private static final Long POST_IDX = 1L; + private static final Long COMMENT_IDX = 1L; + + Comment newComment = Comment.builder() + .commentIdx(COMMENT_IDX) + .comments("새로운 댓글내용") + .user(EntityCreator.createUserEntity()) + .post(EntityCreator.createPostEntity()) + .build(); + + @Nested + @DisplayName("댓글 등록 테스트") + class Input { + @Test + public void 댓글_등록_테스트() { + //given + Comment newComment = EntityCreator.createCommentEntity(); + //mocking + given(postService.findByPostIdx(eq(POST_IDX))).willReturn(newComment.getPost()); + // postService.existsByPostIdx 메서드의 리턴값을 willReturn을 이용해 지정하면 when에서 테스트할 메소드를 호출할때 지정한 값이 사용된다. + //doNothing().when(methodName).postProcess(any()); // void 메소드에 when을 사용하고 싶을때 사용 + + //when + Comment inputtedComment = commentService.inputComments(newComment); + + //then + assertThat(newComment.getCommentIdx()).isEqualTo(inputtedComment.getCommentIdx()); + assertThat(newComment.getComments()).isEqualTo(inputtedComment.getComments()); + assertThat(newComment.getUser().getUserIdx()).isEqualTo(inputtedComment.getUser().getUserIdx()); + assertThat(newComment.getPost().getPostIdx()).isEqualTo(inputtedComment.getPost().getPostIdx()); + } + + @Test + public void 댓글_등록_예외_존재하지_않는_회고글_테스트() { + //given + Comment newComment = EntityCreator.createCommentEntity(); + //mocking + given(postService.findByPostIdx(eq(POST_IDX))).willThrow(new EntityNullException(ErrorInfo.POST_NULL)); + + //when + Throwable throwable = catchThrowable(() -> commentService.inputComments(newComment)); + //then + assertThat(throwable) + .isInstanceOf(EntityNullException.class) + .hasMessage(ErrorInfo.POST_NULL.getErrorMessage()); + } + } + + @Nested + @DisplayName("댓글 조회 테스트") + class Get { + @Test + public void 댓글_리스트_조회_테스트(){ + //given + int page = 0; + int size = 2; + Comment firstComment = EntityCreator.createCommentEntity(); + Comment secondComment = EntityCreator.createCommentEntity(); + secondComment.setCommentIdx(2L); + secondComment.setComments("댓글내용2"); + List arguList = Arrays.asList(firstComment, secondComment); + Pageable pageable = PageRequest.of(page, size); + //mocking + given(commentRepository.findAllByPostIdx(eq(COMMENT_IDX), eq(pageable))).willReturn(arguList); + //when + List commentList = commentService.getCommmentsListByPostIdx(POST_IDX, pageable); + //then + assertThat(commentList.get(0).getCommentIdx()).isEqualTo(firstComment.getCommentIdx()); + assertThat(commentList.get(0).getComments()).isEqualTo(firstComment.getComments()); + assertThat(commentList.get(1).getCommentIdx()).isEqualTo(secondComment.getCommentIdx()); + assertThat(commentList.get(1).getComments()).isEqualTo(secondComment.getComments()); + } + + @Test + public void 댓글_갯수_조회_테스트(){ + //given + Comment firstComment = EntityCreator.createCommentEntity(); + Comment secondComment = EntityCreator.createCommentEntity(); + secondComment.setCommentIdx(2L); + secondComment.setComments("댓글내용2"); + List arguList = Arrays.asList(firstComment, secondComment); + //mocking + given(postService.findByPostIdx(eq(POST_IDX))).willReturn(EntityCreator.createPostEntity()); + given(commentRepository.countCommentByPost(any())).willReturn((long)arguList.size()); + //when + Long count = commentService.getCommmentsCountByPostIdx(POST_IDX); + //then + assertThat(count).isEqualTo(arguList.size()); + } + } + + @Nested + @DisplayName("댓글 수정 테스트") + class Update { + @Test + public void 댓글_수정_테스트() { + //given + Comment oldComment = EntityCreator.createCommentEntity(); + //mocking + given(commentRepository.findById(eq(COMMENT_IDX))).willReturn(Optional.ofNullable(oldComment)); + given(commentRepository.save(any())).willReturn(oldComment); + //when + Comment updatedComment = commentService.updateComments(newComment); + //then + assertThat(oldComment.getCommentIdx()).isEqualTo(updatedComment.getCommentIdx()); + assertThat(oldComment.getComments()).isEqualTo(updatedComment.getComments()); + //수정일자도 업데이트 하는 방법이 있을까? + } + + @Test + public void 댓글_수정_예외_권한_없는_사용자_테스트() { + //given + newComment.getUser().setUserIdx(2L); + Comment oldComment = EntityCreator.createCommentEntity(); + //mocking + given(commentRepository.findById(eq(COMMENT_IDX))).willReturn(Optional.ofNullable(oldComment)); + //when + Throwable throwable = catchThrowable(() -> commentService.updateComments(newComment)); + //then + assertThat(throwable) + .isInstanceOf(AccessDeniedException.class) + .hasMessage(TokenErrorInfo.ACCESS_DENIED.getMessage()); + } + + @Test + public void 댓글_수정_예외_존재하지_않는_댓글_테스트() throws Exception { + //given + //mocking + given(commentRepository.findById(eq(COMMENT_IDX))).willThrow(new EntityNullException(ErrorInfo.COMMENT_NULL)); + //when + Throwable thrown = catchThrowable(() -> commentService.updateComments(newComment)); + //then + assertThat(thrown) + .isInstanceOf(EntityNullException.class) + .hasMessage(ErrorInfo.COMMENT_NULL.getErrorMessage()); + } + } + + @Nested + @DisplayName("댓글 삭제 테스트") + class Delete { + @Test + public void 댓글_삭제_테스트() { + //given + Comment oldComment = EntityCreator.createCommentEntity(); + //mocking + given(commentRepository.findById(eq(COMMENT_IDX))).willReturn(Optional.ofNullable(oldComment)); + doNothing().when(commentRepository).delete(any()); + //when + commentService.deleteComments(oldComment.getUser(), oldComment.getCommentIdx()); + //mocking + given(commentRepository.findById(eq(COMMENT_IDX))).willThrow(new EntityNullException(ErrorInfo.COMMENT_NULL)); + //then + Throwable thrown = catchThrowable(() -> commentService.getCommmentsByIdx(COMMENT_IDX)); + assertThat(thrown) + .isInstanceOf(EntityNullException.class) + .hasMessage(ErrorInfo.COMMENT_NULL.getErrorMessage()); + } + + @Test + public void 댓글_삭제_예외_권한_없는_사용자_테스트() { + //given + newComment.getUser().setUserIdx(2L); + Comment oldComment = EntityCreator.createCommentEntity(); + //mocking + given(commentRepository.findById(eq(COMMENT_IDX))).willReturn(Optional.ofNullable(oldComment)); + //when + Throwable throwable = catchThrowable(() -> commentService.deleteComments(newComment.getUser(), oldComment.getCommentIdx())); + //then + assertThat(throwable) + .isInstanceOf(AccessDeniedException.class) + .hasMessage(TokenErrorInfo.ACCESS_DENIED.getMessage()); + } + + @Test + public void 댓글_삭제_예외_존재하지_않는_댓글_테스트() throws Exception { + //given + Comment oldComment = EntityCreator.createCommentEntity(); + //mocking + given(commentRepository.findById(eq(COMMENT_IDX))).willThrow(new EntityNullException(ErrorInfo.COMMENT_NULL)); + //when + Throwable thrown = catchThrowable(() -> commentService.deleteComments(oldComment.getUser(), oldComment.getCommentIdx())); + //then + assertThat(thrown) + .isInstanceOf(EntityNullException.class) + .hasMessage(ErrorInfo.COMMENT_NULL.getErrorMessage()); + } + } +} diff --git a/src/test/java/com/yapp18/retrospect/web/AbstractControllerTest.java b/src/test/java/com/yapp18/retrospect/web/AbstractControllerTest.java index 6e36caf..9813527 100644 --- a/src/test/java/com/yapp18/retrospect/web/AbstractControllerTest.java +++ b/src/test/java/com/yapp18/retrospect/web/AbstractControllerTest.java @@ -12,7 +12,7 @@ import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; @EncodingConfig -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @AutoConfigureMockMvc public abstract class AbstractControllerTest { @Autowired diff --git a/src/test/java/com/yapp18/retrospect/api/comment/web/CommentControllerTest.java b/src/test/java/com/yapp18/retrospect/web/controller/CommentControllerTest.java similarity index 67% rename from src/test/java/com/yapp18/retrospect/api/comment/web/CommentControllerTest.java rename to src/test/java/com/yapp18/retrospect/web/controller/CommentControllerTest.java index 0a17946..04632f7 100644 --- a/src/test/java/com/yapp18/retrospect/api/comment/web/CommentControllerTest.java +++ b/src/test/java/com/yapp18/retrospect/web/controller/CommentControllerTest.java @@ -1,12 +1,9 @@ -package com.yapp18.retrospect.api.comment.web; +package com.yapp18.retrospect.web.controller; -import com.yapp18.retrospect.api.annotation.WithMockRetrospectUser; +import com.yapp18.retrospect.annotation.WithMockRetrospectUser; import com.yapp18.retrospect.common.EntityCreator; import com.yapp18.retrospect.config.ResponseMessage; import com.yapp18.retrospect.domain.comment.Comment; -import com.yapp18.retrospect.domain.user.Role; -import com.yapp18.retrospect.domain.user.User; -import com.yapp18.retrospect.security.oauth2.AuthProvider; import com.yapp18.retrospect.service.CommentService; import com.yapp18.retrospect.web.AbstractControllerTest; import org.junit.jupiter.api.Test; @@ -22,12 +19,17 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doNothing; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; public class CommentControllerTest extends AbstractControllerTest { @MockBean - CommentService commentService; // 주된 관심사, 위의 Mock 객체들을 주입받는다. + private CommentService commentService; // 주된 관심사, 위의 Mock 객체들을 주입받는다. + + //@Mock은 로직이 삭제된 빈 껍데기라고 보면 된다. 실제로 메서드는 갖고 있지만 내부 구현이 없는 상태이다. + //@Spy는 모든 기능을 가지고 있는 완전한 객체다. + //대체로 Spy보다는 Mock을 사용하길 권고한다. 하지만 외부라이브러리를 이용한 테스트에는 @Spy를 사용하는 것을 추천한다. private static final Long POST_IDX = 1L; private static final Long COMMENT_IDX = 1L; @@ -38,15 +40,21 @@ public class CommentControllerTest extends AbstractControllerTest { // ArgumentCaptor를 사용하면 메서드 호출 여부를 검증하는 과정에서 실제 호출할 때 전달한 인자를 보관할 수 있다. // ArgumentCaptor userArgumentCaptor = ArgumentCaptor.forClass(User.class); + // CommentService는 CommentRepository, PostRepository를 주입받아야 한다. + // 그런데 이렇게 실행하면 테스트는 성공하는 대신에 CommentService 내에 Repository들은 null 상태가 되어있다. + // 객체주입을 하지 않았기 때문이다. given(commentService.inputComments(any())).willReturn(EntityCreator.createCommentEntity()); + // 그럼에도 불구하고 테스트는 통과되는데 해당메서드의 리턴값을 willReturn을 이용해 지정해두었기 때문이다. + // 실질적으로 Repository의 기능을 사용한 것은 아무것도 없다. mockMvc.perform( post("/api/v1/comments") - .content("{\"postIdx\": 1, \"comments\": \"정말 좋은 글입니다.\"}") + .content("{\"postIdx\": 1, \"comments\": \"댓글내용\"}") .contentType(MediaType.APPLICATION_JSON) ).andExpect(status().isCreated()) .andExpect(MockMvcResultMatchers.jsonPath("$.responseMessage").value(ResponseMessage.COMMENT_SAVE.getResponseMessage())) .andExpect(MockMvcResultMatchers.jsonPath("$.data.commentIdx").value(1L)) + .andExpect(MockMvcResultMatchers.jsonPath("$.data.comments").value("댓글내용")) .andExpect(MockMvcResultMatchers.jsonPath("$.data.nickname").value("테스트닉네임")); } @@ -56,7 +64,7 @@ public class CommentControllerTest extends AbstractControllerTest { given(commentService.updateComments(any())).willReturn(EntityCreator.createCommentEntity()); mockMvc.perform( - patch("/api/v1/comments/1") + patch("/api/v1/comments/" + COMMENT_IDX) .content("{\"comments\": \"댓글내용\"}") .contentType(MediaType.APPLICATION_JSON) ).andExpect(status().isCreated()) @@ -72,6 +80,7 @@ public class CommentControllerTest extends AbstractControllerTest { int size = 2; Comment secondComment = EntityCreator.createCommentEntity(); secondComment.setCommentIdx(2L); + secondComment.setComments("댓글내용2"); secondComment.setCreatedAt(LocalDateTime.of(2021, 10, 28, 12, 5, 0)); secondComment.setModifiedAt(LocalDateTime.of(2021, 10, 28, 12, 5, 0)); List commentList = Arrays.asList(EntityCreator.createCommentEntity(), secondComment); @@ -83,6 +92,18 @@ public class CommentControllerTest extends AbstractControllerTest { ).andExpect(status().isOk()) .andExpect(MockMvcResultMatchers.jsonPath("$.responseMessage").value(ResponseMessage.COMMENT_FIND_POSTIDX.getResponseMessage())) .andExpect(MockMvcResultMatchers.jsonPath("$.data[0].commentIdx").value(1L)) - .andExpect(MockMvcResultMatchers.jsonPath("$.data[1].commentIdx").value(2L)); + .andExpect(MockMvcResultMatchers.jsonPath("$.data[0].comments").value("댓글내용")) + .andExpect(MockMvcResultMatchers.jsonPath("$.data[1].commentIdx").value(2L)) + .andExpect(MockMvcResultMatchers.jsonPath("$.data[1].comments").value("댓글내용2")); + } + + @Test + @WithMockRetrospectUser + public void 댓글_삭제_테스트() throws Exception { + doNothing().when(commentService).deleteComments(any(), eq(COMMENT_IDX)); + + mockMvc.perform( + delete("/api/v1/comments/" + COMMENT_IDX) + ).andExpect(status().isNoContent()); } -} +} \ No newline at end of file diff --git "a/src/test/resources/dbunit/Comment/\353\214\223\352\270\200_\353\204\244\352\260\234_\354\241\264\354\236\254.xml" "b/src/test/resources/dbunit/Comment/\353\214\223\352\270\200_\353\204\244\352\260\234_\354\241\264\354\236\254.xml" new file mode 100644 index 0000000..7d2b133 --- /dev/null +++ "b/src/test/resources/dbunit/Comment/\353\214\223\352\270\200_\353\204\244\352\260\234_\354\241\264\354\236\254.xml" @@ -0,0 +1,27 @@ + + + + + + + + + + + \ No newline at end of file diff --git "a/src/test/resources/dbunit/Comment/\353\214\223\352\270\200_\353\221\220\352\260\234_\354\241\264\354\236\254.xml" "b/src/test/resources/dbunit/Comment/\353\214\223\352\270\200_\353\221\220\352\260\234_\354\241\264\354\236\254.xml" new file mode 100644 index 0000000..3342c1b --- /dev/null +++ "b/src/test/resources/dbunit/Comment/\353\214\223\352\270\200_\353\221\220\352\260\234_\354\241\264\354\236\254.xml" @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git "a/src/test/resources/dbunit/Comment/\353\214\223\352\270\200_\355\225\234\352\260\234_\354\241\264\354\236\254.xml" "b/src/test/resources/dbunit/Comment/\353\214\223\352\270\200_\355\225\234\352\260\234_\354\241\264\354\236\254.xml" new file mode 100644 index 0000000..79cb0f9 --- /dev/null +++ "b/src/test/resources/dbunit/Comment/\353\214\223\352\270\200_\355\225\234\352\260\234_\354\241\264\354\236\254.xml" @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git "a/src/test/resources/dbunit/Comment/\353\271\210_\353\214\223\352\270\200_\355\205\214\354\235\264\353\270\224.xml" "b/src/test/resources/dbunit/Comment/\353\271\210_\353\214\223\352\270\200_\355\205\214\354\235\264\353\270\224.xml" new file mode 100644 index 0000000..e83b00b --- /dev/null +++ "b/src/test/resources/dbunit/Comment/\353\271\210_\353\214\223\352\270\200_\355\205\214\354\235\264\353\270\224.xml" @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git "a/src/test/resources/dbunit/Like/\354\212\244\355\201\254\353\236\251_\353\213\244\354\204\257\352\260\234_\354\241\264\354\236\254.xml" "b/src/test/resources/dbunit/Like/\354\212\244\355\201\254\353\236\251_\353\213\244\354\204\257\352\260\234_\354\241\264\354\236\254.xml" new file mode 100644 index 0000000..7011884 --- /dev/null +++ "b/src/test/resources/dbunit/Like/\354\212\244\355\201\254\353\236\251_\353\213\244\354\204\257\352\260\234_\354\241\264\354\236\254.xml" @@ -0,0 +1,27 @@ + + + + + + + + + + + + \ No newline at end of file diff --git "a/src/test/resources/dbunit/Like/\354\212\244\355\201\254\353\236\251_\353\221\220\352\260\234_\354\241\264\354\236\254.xml" "b/src/test/resources/dbunit/Like/\354\212\244\355\201\254\353\236\251_\353\221\220\352\260\234_\354\241\264\354\236\254.xml" new file mode 100644 index 0000000..c4d7038 --- /dev/null +++ "b/src/test/resources/dbunit/Like/\354\212\244\355\201\254\353\236\251_\353\221\220\352\260\234_\354\241\264\354\236\254.xml" @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git "a/src/test/resources/dbunit/Like/\354\212\244\355\201\254\353\236\251_\355\225\234\352\260\234_\354\241\264\354\236\254.xml" "b/src/test/resources/dbunit/Like/\354\212\244\355\201\254\353\236\251_\355\225\234\352\260\234_\354\241\264\354\236\254.xml" new file mode 100644 index 0000000..c6185cf --- /dev/null +++ "b/src/test/resources/dbunit/Like/\354\212\244\355\201\254\353\236\251_\355\225\234\352\260\234_\354\241\264\354\236\254.xml" @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git "a/src/test/resources/dbunit/Post/\355\232\214\352\263\240\352\270\200_\353\204\244\352\260\234_\354\241\264\354\236\254.xml" "b/src/test/resources/dbunit/Post/\355\232\214\352\263\240\352\270\200_\353\204\244\352\260\234_\354\241\264\354\236\254.xml" new file mode 100644 index 0000000..a4c7d0f --- /dev/null +++ "b/src/test/resources/dbunit/Post/\355\232\214\352\263\240\352\270\200_\353\204\244\352\260\234_\354\241\264\354\236\254.xml" @@ -0,0 +1,29 @@ + + + + + + + + + \ No newline at end of file diff --git "a/src/test/resources/dbunit/Post/\355\232\214\352\263\240\352\270\200_\353\221\220\352\260\234_\354\241\264\354\236\254.xml" "b/src/test/resources/dbunit/Post/\355\232\214\352\263\240\352\270\200_\353\221\220\352\260\234_\354\241\264\354\236\254.xml" new file mode 100644 index 0000000..833d7e0 --- /dev/null +++ "b/src/test/resources/dbunit/Post/\355\232\214\352\263\240\352\270\200_\353\221\220\352\260\234_\354\241\264\354\236\254.xml" @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git "a/src/test/resources/dbunit/Post/\355\232\214\352\263\240\352\270\200_\355\225\234\352\260\234_\354\241\264\354\236\254.xml" "b/src/test/resources/dbunit/Post/\355\232\214\352\263\240\352\270\200_\355\225\234\352\260\234_\354\241\264\354\236\254.xml" new file mode 100644 index 0000000..3425689 --- /dev/null +++ "b/src/test/resources/dbunit/Post/\355\232\214\352\263\240\352\270\200_\355\225\234\352\260\234_\354\241\264\354\236\254.xml" @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git "a/src/test/resources/dbunit/User/\354\202\254\354\232\251\354\236\220_\353\221\220\353\252\205_\354\241\264\354\236\254.xml" "b/src/test/resources/dbunit/User/\354\202\254\354\232\251\354\236\220_\353\221\220\353\252\205_\354\241\264\354\236\254.xml" new file mode 100644 index 0000000..cbb1ac6 --- /dev/null +++ "b/src/test/resources/dbunit/User/\354\202\254\354\232\251\354\236\220_\353\221\220\353\252\205_\354\241\264\354\236\254.xml" @@ -0,0 +1,25 @@ + + + + + + + \ No newline at end of file diff --git "a/src/test/resources/dbunit/User/\354\202\254\354\232\251\354\236\220_\355\225\234\353\252\205_\354\241\264\354\236\254.xml" "b/src/test/resources/dbunit/User/\354\202\254\354\232\251\354\236\220_\355\225\234\353\252\205_\354\241\264\354\236\254.xml" new file mode 100644 index 0000000..76ebc98 --- /dev/null +++ "b/src/test/resources/dbunit/User/\354\202\254\354\232\251\354\236\220_\355\225\234\353\252\205_\354\241\264\354\236\254.xml" @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git "a/src/test/resources/dbunit/User/\354\210\230\354\240\225\353\220\234_\354\202\254\354\232\251\354\236\220_\354\240\225\353\263\264.xml" "b/src/test/resources/dbunit/User/\354\210\230\354\240\225\353\220\234_\354\202\254\354\232\251\354\236\220_\354\240\225\353\263\264.xml" new file mode 100644 index 0000000..76354df --- /dev/null +++ "b/src/test/resources/dbunit/User/\354\210\230\354\240\225\353\220\234_\354\202\254\354\232\251\354\236\220_\354\240\225\353\263\264.xml" @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git "a/src/test/resources/dbunit/common/\353\271\210_\355\205\214\354\235\264\353\270\224.xml" "b/src/test/resources/dbunit/common/\353\271\210_\355\205\214\354\235\264\353\270\224.xml" new file mode 100644 index 0000000..c42acca --- /dev/null +++ "b/src/test/resources/dbunit/common/\353\271\210_\355\205\214\354\235\264\353\270\224.xml" @@ -0,0 +1,4 @@ + + + + \ No newline at end of file