Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: 스크랩 관련 Domain, Service 유닛 테스트 코드 작성 #155

Merged
merged 20 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RequiredArgsConstructor
@RestController
@RequestMapping("/api/v1/apply")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import com.gongjakso.server.domain.post.repository.StackNameRepository;
import com.gongjakso.server.global.exception.ApplicationException;
import com.gongjakso.server.global.exception.ErrorCode;
// import com.gongjakso.server.global.util.email.EmailClient;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
Expand Down
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

별도의 Builder 패턴을 사용하지 않고 이렇게 생성자를 만드신 이유 궁금합니다!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Builder 패턴 사용했을 때 id값이 자동으로 설정이 안되어서 수동으로 id값을 설정해주기 위해 사용했습니다 이 부분에 대해서는 한번 다시 찾아보고 수정해보겠습니다!!

Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,18 @@ public Member(String email, String password, String name, String phone, String p
this.major = major;
this.job = job;
}

public Member(Long id, String email, String password, String name, String phone, String profileUrl, String memberType, String loginType, String status, String major, String job){
this.memberId = id;
this.email = email;
this.password = password;
this.name = name;
this.phone = phone;
this.profileUrl = profileUrl;
this.memberType = MemberType.valueOf(memberType);
this.loginType = LoginType.valueOf(loginType);
this.status = status;
this.major = major;
this.job = job;
}
}
27 changes: 27 additions & 0 deletions src/main/java/com/gongjakso/server/domain/post/entity/Post.java
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,31 @@ public void updatePostView(Long postView) {
public void updateStatus(PostStatus status) {
this.status = status;
}

@Builder
public Post(Long id, String title, Member member, String contents, String contestLink, LocalDateTime startDate,
LocalDateTime endDate, LocalDateTime finishDate, Long maxPerson, MeetingMethod meetingMethod,
String meetingCity, String meetingTown, boolean questionMethod, String questionLink, boolean postType,
List<StackName> stackNames, List<Category> categories) {
this.postId = id;
this.title = title;
this.member = member;
this.contents = contents;
this.contestLink = contestLink;
this.status = PostStatus.RECRUITING;
this.startDate = startDate;
this.finishDate = finishDate;
this.endDate = endDate;
this.maxPerson = maxPerson;
this.meetingMethod = meetingMethod;
this.meetingCity = meetingCity;
this.meetingTown = meetingTown;
this.questionMethod = questionMethod;
this.questionLink = questionLink;
this.postType = postType;
this.daysRemaining = finishDate.isBefore(LocalDateTime.now()) ? -1 : ChronoUnit.DAYS.between(LocalDateTime.now(), finishDate);
this.stackNames = stackNames;
this.categories = categories;
this.postView = 0L;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ public PostScrap(Post post, Member member, Boolean scrapStatus){
this.scrapStatus = scrapStatus;
}

@Builder
public PostScrap(long postScrapId, Post post, Member member, Boolean scrapStatus){
this.postScrapId = postScrapId;
this.post = post;
this.member = member;
this.scrapStatus = scrapStatus;
}

public Boolean getScrapStatus(){
return scrapStatus;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ public interface PostScrapRepository extends JpaRepository<PostScrap, Long> {
PostScrap findByPostAndMember(Post post, Member member);
List<PostScrap> findByMemberAndScrapStatus(Member member,boolean scrapStatus);

Page<PostScrap> findAllByMemberAndScrapStatusTrueOrderByPostScrapIdDesc(Member member, Pageable pageable);
Page<PostScrap> findAllByMemberAndPostPostTypeTrueAndPostDeletedAtIsNullAndScrapStatusTrueOrderByPostScrapIdDesc(Member member, Pageable pageable);

Page<PostScrap> findAllByMemberAndPostPostTypeFalseAndPostDeletedAtIsNullAndScrapStatusTrueOrderByPostScrapIdDesc(Member member, Pageable pageable);

}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이런 식으로 쿼리로 리팩토링하신 것 좋은 방법인 것 같습니다!

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
import com.gongjakso.server.global.security.PrincipalDetails;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.*;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand Down Expand Up @@ -374,17 +377,9 @@ public GetPostRelation checkPostRelation(Member member, Long postId) {
public Page<GetProjectRes> getMyScrapProject(Member member, Pageable page){
Pageable pageable = PageRequest.of(page.getPageNumber(), page.getPageSize());

Page<PostScrap> scrapPageList = postScrapRepository.findAllByMemberAndScrapStatusTrueOrderByPostScrapIdDesc(member, pageable);
Page<PostScrap> scrapPageList = postScrapRepository.findAllByMemberAndPostPostTypeTrueAndPostDeletedAtIsNullAndScrapStatusTrueOrderByPostScrapIdDesc(member, pageable);

List<GetProjectRes> filteredProjects = scrapPageList.stream()
.filter(scrap -> {
Post post = scrap.getPost();

//유효한 post만 남기기
return post != null &&
post.isPostType() &&
post.getDeletedAt() == null;
})
List<GetProjectRes> myScrapProjects = scrapPageList.stream()
.map(scrap -> {
Post post = scrap.getPost();
post.getCategories().size();
Expand All @@ -394,24 +389,16 @@ public Page<GetProjectRes> getMyScrapProject(Member member, Pageable page){
.collect(Collectors.toList()); // 리스트로 수집

// 필터링된 리스트를 페이지로 반환
return new PageImpl<>(filteredProjects, pageable, scrapPageList.getTotalElements());
return new PageImpl<>( myScrapProjects, pageable, myScrapProjects.size());
}

@Transactional
public Page<GetContestRes> getMyScrapContest(Member member, Pageable page){
Pageable pageable = PageRequest.of(page.getPageNumber(), page.getPageSize());

Page<PostScrap> scrapPageList = postScrapRepository.findAllByMemberAndScrapStatusTrueOrderByPostScrapIdDesc(member, pageable);
Page<PostScrap> scrapPageList = postScrapRepository.findAllByMemberAndPostPostTypeFalseAndPostDeletedAtIsNullAndScrapStatusTrueOrderByPostScrapIdDesc(member, pageable);

List<GetContestRes> filteredContests = scrapPageList.stream()
.filter(scrap -> {
Post post = scrap.getPost();

//유효한 post만 남기기
return post != null &&
!post.isPostType() &&
post.getDeletedAt() == null;
})
List<GetContestRes> myScrapContests = scrapPageList.stream()
.map(scrap -> {
Post post = scrap.getPost();
post.getCategories().size();
Expand All @@ -421,9 +408,10 @@ public Page<GetContestRes> getMyScrapContest(Member member, Pageable page){
.collect(Collectors.toList()); // 리스트로 수집

// 필터링된 리스트를 페이지로 반환
return new PageImpl<>(filteredContests, pageable, scrapPageList.getTotalElements());
return new PageImpl<>(myScrapContests, pageable, myScrapContests.size());
}


@Transactional
public PostSimpleRes completePost(Member member, Long postId) {
// Validation: Post 논리적 삭제 및 사용자의 권한 여부 확인
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public enum ErrorCode {
//5000: Post Error
NOT_POST_EXCEPTION(HttpStatus.BAD_REQUEST,5000,"공고를 더 이상 생성할 수 없습니다"),
POST_VALUE_EXCEPTION(HttpStatus.BAD_REQUEST,5001,"올바르지 않은 요청 값입니다."),
NOT_FOUNT_SCRAP_EXCEPTION(HttpStatus.NOT_FOUND,5002,"스크랩 정보가 존재하지 않습니다."),
NOT_FOUND_SCRAP_EXCEPTION(HttpStatus.NOT_FOUND,5002,"스크랩 정보가 존재하지 않습니다."),
ALREADY_FINISH_EXCEPTION(HttpStatus.BAD_REQUEST, 5003, "이미 모집 기간이 마감된 공고입니다."),
ILLEGAL_POST_EXCEPTION(HttpStatus.BAD_REQUEST, 5004, "파트별 인원수가 전체 인원수와 일치하지 않습니다.");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@ public static Member buildMember() {
.build();
}

public static Member buildMemberAndId(Long id) {
return new Member(
id,
"[email protected]",
"password123",
"공작소",
"010-1234-5678",
"http://example.com",
MemberType.GENERAL.toString(),
LoginType.KAKAO.toString(),
"상태",
"전공",
"직업"
);
}

public static MemberReq buildMemberReq() {
return MemberReq.builder()
.name("변경 공작소")
Expand Down
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spring Security가 있어서 통합 테스트하려면 Security 테스트 환경을 구축해야 합니다! 제가 아직 안 해놔서.. 꼭 시간 나면 해놓을게요

Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.gongjakso.server.domain.post.controller;

import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;

@AutoConfigureMockMvc
@ExtendWith(MockitoExtension.class)
public class PaginationControllerTest {
/*
MockMvc mockMvc;

private ObjectMapper objectMapper = new ObjectMapper();

@MockBean
private PostService postService;

@MockBean
private PostRepository postRepository;

@MockBean
private MemberRepository memberRepository;

@MockBean
private ApplyService applyService;

@MockBean
private TokenProvider tokenProvider;

@MockBean
private RedisClient redisClient;

@MockBean
private JwtFilter jwtFilter;

private Member member;
private PrincipalDetails principalDetails;

@BeforeEach
void setUp() {
member = MemberUtilTest.buildMemberAndId(1L);
principalDetails = new PrincipalDetails(member);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
principalDetails, null, principalDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}

@Test
@DisplayName("공고 스크랩 저장 및 취소 기능")
void scrapPost() throws Exception {
//given
Post post = PostUtilTest.builderPost(1L, member);
PostScrapRes postScrapRes = PostScrapUtilTest.ScrapPostRes(post.getPostId(), member.getMemberId(), true);
given(postService.scrapPost(any(Member.class), anyLong())).willReturn(postScrapRes);
String resJson = objectMapper.writeValueAsString(postScrapRes);

mockMvc.perform(post("/api/v1/post/{id}", post.getPostId())
.contentType(MediaType.APPLICATION_JSON)
.principal((Principal) principalDetails))
.andExpect(status().isOk())
.andExpect(content().json(resJson))
.andDo(print());

verify(postService).scrapPost(any(Member.class), any(Long.class));
}

*/
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.gongjakso.server.domain.post.domain;


import com.gongjakso.server.domain.member.entity.Member;
import com.gongjakso.server.domain.member.util.MemberUtilTest;
import com.gongjakso.server.domain.post.entity.Post;
import com.gongjakso.server.domain.post.entity.PostScrap;
import com.gongjakso.server.domain.post.util.PostScrapUtilTest;
import com.gongjakso.server.domain.post.util.PostUtilTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

@DisplayName("PostScrap 도메인 테스트")
public class ScrapDomainTest{

private Post post;
private Member member;

@BeforeEach
public void setUp() {
member = MemberUtilTest.buildMemberAndId(1L);
post = PostUtilTest.builderPost(1L, member);
}

@Nested
@DisplayName("Builder테스트")
class BuilderTests {

@Test
@DisplayName("Id없이 빌드 되어야 함")
public void testPostScrapBuilder() {
PostScrap postScrap = PostScrapUtilTest.builderPostScrap(post, post.getMember());
System.out.println(postScrap.getMember());
System.out.println(member);
assertThat(postScrap.getPost()).isEqualTo(post);
assertThat(postScrap.getMember()).isEqualTo(member);
assertThat(postScrap.getScrapStatus()).isTrue();
}

@Test
@DisplayName("Id와 함께 빌드 되어야 함")
public void testPostScrapBuilderWithId() {
Long postScrapId = 1L;
PostScrap postScrap = PostScrapUtilTest.builderPostScrapWithPostAndMember(postScrapId, post, post.getMember());
assertThat(postScrap.getPostScrapId()).isEqualTo(postScrapId);
assertThat(postScrap.getPost()).isEqualTo(post);
assertThat(postScrap.getMember()).isEqualTo(member);
assertThat(postScrap.getScrapStatus()).isTrue();
}
}
}
Loading
Loading