Skip to content

Commit

Permalink
fix: 잘못된 카테고리 생성 요청에 대한 예외 처리 (#159)
Browse files Browse the repository at this point in the history
* [#158] fix: 이미 카테고리 존재 시, 부모, 형제가 주어지지 않은 카테고리를 또 생성하는 경우 예외처리

* [#158] test: 카테고리 관련 테스트코드 보강
  • Loading branch information
shin-mallang authored Dec 12, 2023
1 parent 4412fbe commit 2fd131a
Show file tree
Hide file tree
Showing 15 changed files with 232 additions and 101 deletions.
36 changes: 18 additions & 18 deletions src/main/java/com/mallang/category/TieredCategory.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,19 @@ protected TieredCategory(String name, Member owner) {
this.owner = owner;
}

public void create(
@Nullable T parent,
@Nullable T prevSibling,
@Nullable T nextSibling,
TieredCategoryValidator validator
) {
if (isNulls(parent, prevSibling, nextSibling)) {
validator.validateNoCategories(owner);
return;
}
updateHierarchy(parent, prevSibling, nextSibling);
}

public abstract void validateOwner(Member member);

public void updateHierarchy(
Expand Down Expand Up @@ -107,6 +120,9 @@ private void validateParentAndChildRelation(
@Nullable T nextSibling
) {
if (isNulls(prevSibling, nextSibling)) {
if (parent == null) {
throw new CategoryHierarchyViolationException("카테고리 계층구조 변경 시 부모나 형제들 중 최소 하나와의 관계가 주어져야 합니다.");
}
validateNoChildrenInParent(parent);
}
validateWhenNonNullWithFailCond(
Expand All @@ -123,25 +139,9 @@ private void validateParentAndChildRelation(


private void validateNoChildrenInParent(T parent) {
if (parent == null) {
T root = getRoot();
if (equals(root) && root.getPreviousSibling() == null && root.getNextSibling() == null) {
return;
}
throw new CategoryHierarchyViolationException("존재하는 다른 최상위 카테고리와의 관계가 명시되지 않았습니다.");
} else {
if (!parent.getChildren().isEmpty()) {
throw new CategoryHierarchyViolationException("주어진 부모의 자식 카테고리와의 관계가 명시되지 않았습니다.");
}
}
}

private T getRoot() {
T root = self();
while (root.getParent() != null) {
root = root.getParent();
if (!parent.getChildren().isEmpty()) {
throw new CategoryHierarchyViolationException("주어진 부모의 자식 카테고리와의 관계가 명시되지 않았습니다.");
}
return root;
}

private void validateDuplicatedNameWhenParticipated(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.mallang.category;

import com.mallang.auth.domain.Member;

public interface TieredCategoryValidator {

void validateNoCategories(Member member);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.mallang.post.domain.Post;
import com.mallang.post.domain.PostCategory;
import com.mallang.post.domain.PostCategoryRepository;
import com.mallang.post.domain.PostCategoryValidator;
import com.mallang.post.domain.PostRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -25,26 +26,26 @@ public class PostCategoryService {
private final PostRepository postRepository;
private final MemberRepository memberRepository;
private final PostCategoryRepository postCategoryRepository;
private final PostCategoryValidator postCategoryValidator;

public Long create(CreatePostCategoryCommand command) {
Member member = memberRepository.getById(command.memberId());
Blog blog = blogRepository.getByName(command.blogName());
PostCategory postCategory = new PostCategory(command.name(), member, blog);
updateHierarchy(postCategory, command.parentId(), command.prevId(), command.nextId());
PostCategory parent = postCategoryRepository.getByIdIfIdNotNull(command.parentId());
PostCategory prev = postCategoryRepository.getByIdIfIdNotNull(command.prevId());
PostCategory next = postCategoryRepository.getByIdIfIdNotNull(command.nextId());
postCategory.create(parent, prev, next, postCategoryValidator);
return postCategoryRepository.save(postCategory).getId();
}

public void updateHierarchy(UpdatePostCategoryHierarchyCommand command) {
Member member = memberRepository.getById(command.memberId());
PostCategory target = postCategoryRepository.getById(command.categoryId());
target.validateOwner(member);
updateHierarchy(target, command.parentId(), command.prevId(), command.nextId());
}

private void updateHierarchy(PostCategory target, Long parentId, Long prevId, Long nextId) {
PostCategory parent = postCategoryRepository.getByIdIfIdNotNull(parentId);
PostCategory prev = postCategoryRepository.getByIdIfIdNotNull(prevId);
PostCategory next = postCategoryRepository.getByIdIfIdNotNull(nextId);
PostCategory parent = postCategoryRepository.getByIdIfIdNotNull(command.parentId());
PostCategory prev = postCategoryRepository.getByIdIfIdNotNull(command.prevId());
PostCategory next = postCategoryRepository.getByIdIfIdNotNull(command.nextId());
target.updateHierarchy(parent, prev, next);
}

Expand Down
17 changes: 9 additions & 8 deletions src/main/java/com/mallang/post/application/StarGroupService.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.mallang.post.domain.star.PostStarRepository;
import com.mallang.post.domain.star.StarGroup;
import com.mallang.post.domain.star.StarGroupRepository;
import com.mallang.post.domain.star.StarGroupValidator;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -21,25 +22,25 @@ public class StarGroupService {
private final MemberRepository memberRepository;
private final PostStarRepository postStarRepository;
private final StarGroupRepository starGroupRepository;
private final StarGroupValidator starGroupValidator;

public Long create(CreateStarGroupCommand command) {
Member member = memberRepository.getById(command.memberId());
StarGroup group = new StarGroup(command.name(), member);
updateHierarchy(group, command.parentId(), command.prevId(), command.nextId());
StarGroup parent = starGroupRepository.getByIdIfIdNotNull(command.parentId());
StarGroup prev = starGroupRepository.getByIdIfIdNotNull(command.prevId());
StarGroup next = starGroupRepository.getByIdIfIdNotNull(command.nextId());
group.create(parent, prev, next, starGroupValidator);
return starGroupRepository.save(group).getId();
}

public void updateHierarchy(UpdateStarGroupHierarchyCommand command) {
Member member = memberRepository.getById(command.memberId());
StarGroup target = starGroupRepository.getById(command.groupId());
target.validateOwner(member);
updateHierarchy(target, command.parentId(), command.prevId(), command.nextId());
}

private void updateHierarchy(StarGroup target, Long parentId, Long prevId, Long nextId) {
StarGroup parent = starGroupRepository.getByIdIfIdNotNull(parentId);
StarGroup prev = starGroupRepository.getByIdIfIdNotNull(prevId);
StarGroup next = starGroupRepository.getByIdIfIdNotNull(nextId);
StarGroup parent = starGroupRepository.getByIdIfIdNotNull(command.parentId());
StarGroup prev = starGroupRepository.getByIdIfIdNotNull(command.prevId());
StarGroup next = starGroupRepository.getByIdIfIdNotNull(command.nextId());
target.updateHierarchy(parent, prev, next);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mallang.post.domain;

import com.mallang.auth.domain.Member;
import com.mallang.post.exception.NotFoundPostCategoryException;
import jakarta.annotation.Nullable;
import org.springframework.data.jpa.repository.JpaRepository;
Expand All @@ -17,4 +18,6 @@ default PostCategory getByIdIfIdNotNull(@Nullable Long categoryId) {
}
return getById(categoryId);
}

boolean existsByOwner(Member member);
}
21 changes: 21 additions & 0 deletions src/main/java/com/mallang/post/domain/PostCategoryValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.mallang.post.domain;

import com.mallang.auth.domain.Member;
import com.mallang.category.CategoryHierarchyViolationException;
import com.mallang.category.TieredCategoryValidator;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@RequiredArgsConstructor
@Component
public class PostCategoryValidator implements TieredCategoryValidator {

private final PostCategoryRepository postCategoryRepository;

@Override
public void validateNoCategories(Member member) {
if (postCategoryRepository.existsByOwner(member)) {
throw new CategoryHierarchyViolationException("이미 존재하는 카테고리가 있습니다.");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mallang.post.domain.star;

import com.mallang.auth.domain.Member;
import com.mallang.post.exception.NotFoundStarGroupException;
import jakarta.annotation.Nullable;
import org.springframework.data.jpa.repository.JpaRepository;
Expand All @@ -17,4 +18,6 @@ default StarGroup getByIdIfIdNotNull(@Nullable Long id) {
}
return getById(id);
}

boolean existsByOwner(Member member);
}
21 changes: 21 additions & 0 deletions src/main/java/com/mallang/post/domain/star/StarGroupValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.mallang.post.domain.star;

import com.mallang.auth.domain.Member;
import com.mallang.category.CategoryHierarchyViolationException;
import com.mallang.category.TieredCategoryValidator;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@RequiredArgsConstructor
@Component
public class StarGroupValidator implements TieredCategoryValidator {

private final StarGroupRepository starGroupRepository;

@Override
public void validateNoCategories(Member member) {
if (starGroupRepository.existsByOwner(member)) {
throw new CategoryHierarchyViolationException("이미 존재하는 즐겨찾기 그룹이 있습니다.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,25 @@ class 카테고리_생성_API {
값이_존재한다(ID를_추출한다(응답));
}

@Test
void 이미_카테고리가_존재하는데_부모와_형제와의_관계가_모두_주어지지_않은_카테고리_생성_시_예외() {
// given
카테고리_생성_요청(말랑_세션_ID, Spring_카테고리_생성_요청);
var 다른_루트_카테고리_생성_요청 = new CreatePostCategoryRequest(
말랑_블로그_이름,
"Other",
null,
null,
null
);

// when
var 응답 = 카테고리_생성_요청(말랑_세션_ID, 다른_루트_카테고리_생성_요청);

// then
응답_상태를_검증한다(응답, 잘못된_요청);
}

@Test
void 하위_카테고리를_생성한다() {
// given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ protected void setUp() {
var 포스트2_ID = 포스트_생성(말랑_세션_ID, 포스트2_데이터);
var 포스트3_ID = 포스트_생성(말랑_세션_ID, 포스트3_데이터);
Long group1 = ID를_추출한다(즐겨찾기_그룹_생성_요청(동훈_세션_ID, "group1", null, null, null));
Long group2 = ID를_추출한다(즐겨찾기_그룹_생성_요청(동훈_세션_ID, "group2", null, null, null));
Long group2 = ID를_추출한다(즐겨찾기_그룹_생성_요청(동훈_세션_ID, "group2", null, group1, null));
포스트_즐겨찾기_요청(동훈_세션_ID, 포스트1_ID, 블로그_이름, group1, null);
포스트_즐겨찾기_요청(동훈_세션_ID, 포스트2_ID, 블로그_이름, group2, null);
포스트_즐겨찾기_요청(동훈_세션_ID, 포스트3_ID, 블로그_이름, null, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,24 @@ class 즐겨찾기_그룹_생성_API {
값이_존재한다(ID를_추출한다(응답));
}

@Test
void 이미_즐겨찾기_그룹이_존재하는데_부모와_형제와의_관계가_모두_주어지지_않은_그룹_생성_시_예외() {
// given
즐겨찾기_그룹_생성_요청(말랑_세션_ID, Spring_즐겨찾기_그룹_생성_요청);
var 다른_루트_그룹_생성_요청 = new CreateStarGroupRequest(
"Other",
null,
null,
null
);

// when
var 응답 = 즐겨찾기_그룹_생성_요청(말랑_세션_ID, 다른_루트_그룹_생성_요청);

// then
응답_상태를_검증한다(응답, 잘못된_요청);
}

@Test
void 하위_즐겨찾기_그룹를_생성한다() {
// given
Expand Down
Loading

0 comments on commit 2fd131a

Please sign in to comment.