-
Notifications
You must be signed in to change notification settings - Fork 0
feature/#109 Post 테스트 코드 작성 #117
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
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
42d410e
feat: Post 도메인 성공 테스트 및 클래스 생성
LeeShinHaeng cd15f46
refactor: Post 도메인 테스트 수정
LeeShinHaeng ffa6419
feat: PostServiceTest 코드 작성을 위한 세팅
LeeShinHaeng e36acfa
fix: 테스트 중 발견한 createPost 오류 수정
LeeShinHaeng 8c9f6ab
feat: createPost 테스트 구현
LeeShinHaeng 23bb9a3
feat: createdAt을 사용하지 않는 테스트 구현
LeeShinHaeng 5b0ab3f
feat: TestEntityUtils를 적용해 createdAt 사용 테스트 구현
LeeShinHaeng 6d85570
Merge branch 'develop' into feature/#109-post-test-code
LeeShinHaeng cbc8ac4
fix: CodeRabbit 리뷰 반영, 테스트 케이스 수정 및 null 체크 보완
LeeShinHaeng cb058ba
fix: FakeUserService 삭제 후 테스트용SecurityContext 대체
LeeShinHaeng 0e6a106
fix: UserServiceTest 초기화 부분 수정
LeeShinHaeng File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
166 changes: 166 additions & 0 deletions
166
aics-api/src/testFixtures/java/post/application/PostServiceTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
package post.application; | ||
|
||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertNotEquals; | ||
|
||
import kgu.developers.api.post.application.PostService; | ||
import kgu.developers.api.post.presentation.exception.PostNotFoundException; | ||
import kgu.developers.api.post.presentation.request.PostRequest; | ||
import kgu.developers.api.post.presentation.response.PostDetailResponse; | ||
import kgu.developers.api.post.presentation.response.PostPersistResponse; | ||
import kgu.developers.api.post.presentation.response.PostSummaryPageResponse; | ||
import kgu.developers.api.user.application.UserService; | ||
import kgu.developers.domain.post.domain.Category; | ||
import kgu.developers.domain.post.domain.Post; | ||
import kgu.developers.domain.user.domain.Major; | ||
import kgu.developers.domain.user.domain.User; | ||
import mock.FakePostRepository; | ||
import mock.FakeUserRepository; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.data.domain.PageRequest; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.context.SecurityContext; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.security.core.userdetails.UserDetails; | ||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||
|
||
public class PostServiceTest { | ||
private PostService postService; | ||
|
||
@BeforeEach | ||
public void init() { | ||
FakePostRepository fakePostRepository = new FakePostRepository(); | ||
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(); | ||
FakeUserRepository fakeUserRepository = new FakeUserRepository(); | ||
UserService userService = new UserService(bCryptPasswordEncoder, fakeUserRepository); | ||
|
||
this.postService = new PostService(fakePostRepository, userService); | ||
|
||
fakeUserRepository.save(User.builder() | ||
.id("202411345") | ||
.password(bCryptPasswordEncoder.encode("password1234")) | ||
.name("홍길동") | ||
.email("test@kyonggi.ac.kr") | ||
.phone("010-1234-5678") | ||
.major(Major.CSE) | ||
.build()); | ||
|
||
UserDetails user = userService.getUserById("202411345"); | ||
SecurityContext context = SecurityContextHolder.getContext(); | ||
context.setAuthentication( | ||
new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities()) | ||
); | ||
|
||
fakePostRepository.save(Post.create( | ||
"테스트용 제목1", "테스트용 내용1", | ||
Category.DEPT_INFO, userService.getUserById("202411345") | ||
)); | ||
|
||
fakePostRepository.save(Post.create( | ||
"테스트용 제목2", "테스트용 내용2", | ||
Category.DEPT_INFO, userService.getUserById("202411345") | ||
)); | ||
} | ||
|
||
@Test | ||
@DisplayName("createPost는 게시글을 생성할 수 있다") | ||
public void createPost_Success() { | ||
// given | ||
PostRequest request = PostRequest.builder() | ||
.title("테스트용 제목3") | ||
.content("테스트용 내용3") | ||
.build(); | ||
Category category = Category.DEPT_INFO; | ||
|
||
// when | ||
PostPersistResponse response = postService.createPost(request, category); | ||
|
||
// then | ||
assertEquals(3, response.postId()); | ||
|
||
// when | ||
PostDetailResponse created = postService.getPostById(response.postId()); | ||
|
||
// then | ||
assertEquals(request.title(), created.title()); | ||
assertEquals(request.content(), created.content()); | ||
assertEquals(category.getDescription(), created.category()); | ||
} | ||
|
||
@Test | ||
@DisplayName("getPostById는 게시글을 조회할 수 있다") | ||
public void getPostById_Success() { | ||
// given | ||
Long postId = 1L; | ||
|
||
// when | ||
PostDetailResponse response = postService.getPostById(postId); | ||
|
||
// then | ||
assertEquals(postId, response.postId()); | ||
} | ||
|
||
@Test | ||
@DisplayName("getPostById는 존재하지 않는 ID로 조회시 PostNotFoundException을 발생시킨다") | ||
public void getPostById_Throws_PostNotFoundException() { | ||
// given | ||
Long postId = 10L; | ||
|
||
// when | ||
// then | ||
assertThatThrownBy( | ||
() -> postService.getPostById(postId) | ||
).isInstanceOf(PostNotFoundException.class); | ||
} | ||
|
||
@Test | ||
@DisplayName("getPostsByKeywordAndCategory는 게시글을 페이징 조회할 수 있다") | ||
public void getPostsByKeywordAndCategory_Success() { | ||
// given | ||
String keyword = "제목"; | ||
Category category = Category.DEPT_INFO; | ||
int page = 0; | ||
int size = 10; | ||
|
||
// when | ||
PostSummaryPageResponse posts = postService.getPostsByKeywordAndCategory( | ||
PageRequest.of(page, size), keyword, category | ||
); | ||
|
||
// then | ||
assertEquals(2, posts.contents().size()); | ||
} | ||
|
||
@Test | ||
@DisplayName("togglePostPinStatus는 게시글의 고정 상태를 변경할 수 있다") | ||
public void togglePostPinStatus_Success() { | ||
// given | ||
Long postId = 1L; | ||
PostDetailResponse before = postService.getPostById(postId); | ||
|
||
// when | ||
postService.togglePostPinStatus(postId); | ||
|
||
// then | ||
PostDetailResponse after = postService.getPostById(postId); | ||
assertNotEquals(before.isPinned(), after.isPinned()); | ||
} | ||
|
||
@Test | ||
@DisplayName("deletePost 이후 게시글을 조회할 수 없다") | ||
public void deletePost_Throws_PostNotFoundException() { | ||
// given | ||
Long postId = 1L; | ||
|
||
// when | ||
postService.deletePost(postId); | ||
|
||
// then | ||
assertThatThrownBy( | ||
() -> postService.getPostById(postId) | ||
).isInstanceOf(PostNotFoundException.class); | ||
} | ||
} |
4 changes: 4 additions & 0 deletions
4
aics-api/src/testFixtures/java/post/presentation/PostControllerTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package post.presentation; | ||
|
||
public class PostControllerTest { | ||
} |
87 changes: 87 additions & 0 deletions
87
aics-domain/src/testFixtures/java/mock/FakePostRepository.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package mock; | ||
|
||
import kgu.developers.common.response.PageableResponse; | ||
import kgu.developers.common.response.PaginatedListResponse; | ||
import kgu.developers.domain.post.domain.Category; | ||
import kgu.developers.domain.post.domain.Post; | ||
import kgu.developers.domain.post.domain.PostRepository; | ||
import org.springframework.data.domain.Pageable; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.Comparator; | ||
import java.util.List; | ||
import java.util.Optional; | ||
import java.util.concurrent.atomic.AtomicLong; | ||
import java.util.stream.Collectors; | ||
|
||
public class FakePostRepository implements PostRepository { | ||
private final List<Post> data = Collections.synchronizedList(new ArrayList<>()); | ||
private final AtomicLong autoGeneratedId = new AtomicLong(0); | ||
|
||
@Override | ||
public Post save(Post post) { | ||
if (post == null) { | ||
throw new IllegalArgumentException("게시글은 null일 수 없습니다."); | ||
} | ||
if (post.getTitle() == null || post.getContent() == null) { | ||
throw new IllegalArgumentException("제목과 내용은 필수 입력값입니다."); | ||
} | ||
|
||
Post newPost = Post.builder() | ||
.id(autoGeneratedId.incrementAndGet()) | ||
.title(post.getTitle()) | ||
.content(post.getContent()) | ||
.views(post.getViews()) | ||
.category(post.getCategory()) | ||
.author(post.getAuthor()) | ||
.isPinned(post.isPinned()) | ||
.comments(new ArrayList<>(post.getComments())) | ||
.file(post.getFile()) | ||
.build(); | ||
|
||
TestEntityUtils.setCreatedAt(newPost, LocalDateTime.now()); | ||
|
||
data.add(newPost); | ||
return newPost; | ||
} | ||
|
||
@Override | ||
public PaginatedListResponse<Post> findAllByTitleContainingAndCategoryOrderByCreatedAtDesc( | ||
String keyword, Category category, Pageable pageable | ||
) { | ||
List<Post> filteredPosts = data.stream() | ||
.filter( | ||
post -> post.getTitle().contains(keyword) && post.getCategory().equals(category) | ||
) | ||
.sorted(Comparator.comparing(Post::getCreatedAt).reversed()) | ||
.collect(Collectors.toList()); | ||
|
||
int start = (int) pageable.getOffset(); | ||
int end = Math.min(start + pageable.getPageSize(), filteredPosts.size()); | ||
|
||
List<Post> paginatedPosts = start > filteredPosts.size() ? | ||
Collections.emptyList() : | ||
filteredPosts.subList(start, end); | ||
|
||
List<Long> ids = paginatedPosts.stream() | ||
.map(Post::getId) | ||
.toList(); | ||
|
||
return PaginatedListResponse.of(paginatedPosts, PageableResponse.of(pageable, ids)); | ||
} | ||
|
||
@Override | ||
public Optional<Post> findById(Long postId) { | ||
return data.stream() | ||
.filter(post -> post.getId().equals(postId)) | ||
.findAny(); | ||
} | ||
|
||
@Override | ||
public void deleteAllByDeletedAtBefore(int retentionDays) { | ||
LocalDateTime threshold = LocalDateTime.now().minusDays(retentionDays); | ||
data.removeIf(post -> post.getDeletedAt() != null && post.getDeletedAt().isBefore(threshold)); | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
aics-domain/src/testFixtures/java/mock/TestEntityUtils.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package mock; | ||
|
||
import kgu.developers.common.domain.BaseTimeEntity; | ||
|
||
import java.lang.reflect.Field; | ||
import java.time.LocalDateTime; | ||
|
||
public class TestEntityUtils { | ||
public static void setCreatedAt(BaseTimeEntity entity, LocalDateTime createdAt) { | ||
if (entity == null || createdAt == null) { | ||
throw new IllegalArgumentException("entity와 createdAt은 null이 될 수 없습니다."); | ||
} | ||
|
||
try { | ||
Field field = BaseTimeEntity.class.getDeclaredField("createdAt"); | ||
field.setAccessible(true); | ||
field.set(entity, createdAt); | ||
} catch (NoSuchFieldException | IllegalAccessException e) { | ||
throw new RuntimeException("TestEntityUtils에서 createdAt 설정 실패", e); | ||
} | ||
} | ||
} | ||
|
4 changes: 4 additions & 0 deletions
4
aics-domain/src/testFixtures/java/post/application/PostServiceTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package post.application; | ||
|
||
public class PostServiceTest { | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.