From 4d4b16461bafc6136d412c807d86c38a9db83db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EA=B2=BD=EB=AF=B8?= <109158497+kyum-q@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:16:08 +0900 Subject: [PATCH] =?UTF-8?q?[BUG]=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EB=B0=98?= =?UTF-8?q?=20=EC=A0=95=EA=B7=9C=ED=99=94=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20?= =?UTF-8?q?=ED=85=9C=ED=94=8C=EB=A6=BF=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=8B=9C=20=ED=95=B4=EB=8B=B9=20=ED=85=9C=ED=94=8C=EB=A6=BF?= =?UTF-8?q?=EC=9D=98=20ModifiedAt=20=EB=B3=80=EA=B2=BD=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20(#927)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/auditing/BaseTimeEntity.java | 6 +-- .../SkipModifiedAtBaseTimeEntity.java | 40 +++++++++++++++++++ .../codezap/template/domain/Template.java | 8 +++- .../java/codezap/fixture/CategoryFixture.java | 2 +- .../likes/service/LikesServiceTest.java | 24 ++++++++--- .../service/SourceCodeServiceTest.java | 37 ----------------- .../template/service/TemplateServiceTest.java | 33 ++++++++++++++- .../TemplateApplicationServiceTest.java | 37 ++++++++++++++++- 8 files changed, 135 insertions(+), 52 deletions(-) create mode 100644 backend/src/main/java/codezap/global/auditing/SkipModifiedAtBaseTimeEntity.java diff --git a/backend/src/main/java/codezap/global/auditing/BaseTimeEntity.java b/backend/src/main/java/codezap/global/auditing/BaseTimeEntity.java index 9afcea565..898f54735 100644 --- a/backend/src/main/java/codezap/global/auditing/BaseTimeEntity.java +++ b/backend/src/main/java/codezap/global/auditing/BaseTimeEntity.java @@ -15,13 +15,13 @@ @EntityListeners(AuditingEntityListener.class) @MappedSuperclass @Getter -public class BaseTimeEntity { +public abstract class BaseTimeEntity { @CreatedDate @Column(updatable = false, nullable = false) - private LocalDateTime createdAt; + protected LocalDateTime createdAt; @LastModifiedDate @Column(nullable = false) - private LocalDateTime modifiedAt; + protected LocalDateTime modifiedAt; } diff --git a/backend/src/main/java/codezap/global/auditing/SkipModifiedAtBaseTimeEntity.java b/backend/src/main/java/codezap/global/auditing/SkipModifiedAtBaseTimeEntity.java new file mode 100644 index 000000000..3f0015f7e --- /dev/null +++ b/backend/src/main/java/codezap/global/auditing/SkipModifiedAtBaseTimeEntity.java @@ -0,0 +1,40 @@ +package codezap.global.auditing; + +import java.time.LocalDateTime; + +import jakarta.persistence.MappedSuperclass; +import jakarta.persistence.PostLoad; +import jakarta.persistence.PostPersist; +import jakarta.persistence.PostUpdate; +import jakarta.persistence.PreUpdate; +import jakarta.persistence.Transient; + +@MappedSuperclass +public abstract class SkipModifiedAtBaseTimeEntity extends BaseTimeEntity { + + @Transient + private LocalDateTime lastModifiedAt; + + @Transient + private boolean isModified = true; + + @PreUpdate + private void preUpdate() { + if (!isModified && lastModifiedAt != null) { + modifiedAt = lastModifiedAt; + return; + } + isModified = true; + } + + @PostLoad + @PostPersist + @PostUpdate + private void postLoad() { + lastModifiedAt = modifiedAt; + } + + public void skipModifiedAtUpdate() { + isModified = false; + } +} diff --git a/backend/src/main/java/codezap/template/domain/Template.java b/backend/src/main/java/codezap/template/domain/Template.java index 0e7a4c8a5..04ca63502 100644 --- a/backend/src/main/java/codezap/template/domain/Template.java +++ b/backend/src/main/java/codezap/template/domain/Template.java @@ -1,5 +1,6 @@ package codezap.template.domain; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -18,7 +19,7 @@ import org.hibernate.annotations.DynamicUpdate; import codezap.category.domain.Category; -import codezap.global.auditing.BaseTimeEntity; +import codezap.global.auditing.SkipModifiedAtBaseTimeEntity; import codezap.member.domain.Member; import lombok.AccessLevel; import lombok.AllArgsConstructor; @@ -32,7 +33,7 @@ @AllArgsConstructor @Getter @EqualsAndHashCode(of = "id", callSuper = false) -public class Template extends BaseTimeEntity { +public class Template extends SkipModifiedAtBaseTimeEntity { private static final Long LIKES_COUNT_DEFAULT = 0L; @@ -73,6 +74,7 @@ public Template(Member member, String title, String description, Category catego } public void updateTemplate(String title, String description, Category category, Visibility visibility) { + this.modifiedAt = LocalDateTime.now(); this.title = title; this.description = description; this.category = category; @@ -88,10 +90,12 @@ public boolean isPrivate() { } public void increaseLike() { + skipModifiedAtUpdate(); this.likesCount++; } public void cancelLike() { + skipModifiedAtUpdate(); if (this.likesCount <= LIKES_COUNT_DEFAULT) { return; } diff --git a/backend/src/test/java/codezap/fixture/CategoryFixture.java b/backend/src/test/java/codezap/fixture/CategoryFixture.java index 686590fe0..ebffa6a29 100644 --- a/backend/src/test/java/codezap/fixture/CategoryFixture.java +++ b/backend/src/test/java/codezap/fixture/CategoryFixture.java @@ -13,6 +13,6 @@ public static Category getSecondCategory() { } public static Category get(Member member) { - return new Category(1L, member, "카테고리", false); + return new Category("카테고리", member); } } diff --git a/backend/src/test/java/codezap/likes/service/LikesServiceTest.java b/backend/src/test/java/codezap/likes/service/LikesServiceTest.java index 2e6fa2780..fa0a42ae7 100644 --- a/backend/src/test/java/codezap/likes/service/LikesServiceTest.java +++ b/backend/src/test/java/codezap/likes/service/LikesServiceTest.java @@ -3,20 +3,21 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; +import java.time.LocalDateTime; import java.util.List; +import jakarta.persistence.EntityManager; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.PageRequest; import codezap.category.domain.Category; import codezap.fixture.CategoryFixture; import codezap.fixture.MemberFixture; import codezap.fixture.TemplateFixture; import codezap.global.ServiceTest; -import codezap.global.pagination.FixedPage; import codezap.likes.domain.Likes; import codezap.member.domain.Member; import codezap.template.domain.Template; @@ -26,22 +27,30 @@ class LikesServiceTest extends ServiceTest { @Autowired private LikesService likesService; + @Autowired + private EntityManager entityManager; + @Nested @DisplayName("좋아요") class LikesTest { @Test - @DisplayName("성공") + @DisplayName("성공: 템플릿 수정 시간은 변경되지 않는다.") void success() { Member member = memberRepository.save(MemberFixture.getFirstMember()); Template template = templateRepository.save(TemplateFixture.get( member, categoryRepository.save(CategoryFixture.getFirstCategory()) )); + LocalDateTime modifiedAtBeforeLike = template.getModifiedAt(); likesService.like(member, template.getId()); + entityManager.flush(); - assertThat(likesRepository.existsByMemberAndTemplate(member, template)).isTrue(); + assertAll( + () -> assertThat(likesRepository.existsByMemberAndTemplate(member, template)).isTrue(), + () -> assertThat(template.getModifiedAt()).isEqualTo(modifiedAtBeforeLike) + ); } @Test @@ -71,10 +80,15 @@ void success() { Category category = categoryRepository.save(CategoryFixture.getFirstCategory()); Template template = templateRepository.save(TemplateFixture.get(member, category)); likesService.like(member, template.getId()); + LocalDateTime modifiedAtBeforeLike = template.getModifiedAt(); likesService.cancelLike(member, template.getId()); + entityManager.flush(); - assertThat(likesRepository.existsByMemberAndTemplate(member, template)).isFalse(); + assertAll( + () -> assertThat(likesRepository.existsByMemberAndTemplate(member, template)).isFalse(), + () -> assertThat(template.getModifiedAt()).isEqualTo(modifiedAtBeforeLike) + ); } @Test diff --git a/backend/src/test/java/codezap/template/service/SourceCodeServiceTest.java b/backend/src/test/java/codezap/template/service/SourceCodeServiceTest.java index 54066906d..49517fcf3 100644 --- a/backend/src/test/java/codezap/template/service/SourceCodeServiceTest.java +++ b/backend/src/test/java/codezap/template/service/SourceCodeServiceTest.java @@ -178,43 +178,6 @@ void findSourceCodesByTemplate_WhenSourceCodeNotExist() { @DisplayName("소스 코드 수정") class UpdateSourceCodes { - @Test - @DisplayName("성공: 기존 소스 코드 제목, 내용 수정 및 새로운 소스 코드 추가") - void updateSourceCodes() { - // given - Template template = createSavedTemplate(); - SourceCode sourceCode1 = sourceCodeRepository.save(SourceCodeFixture.get(template, 1)); - SourceCode sourceCode2 = sourceCodeRepository.save(SourceCodeFixture.get(template, 2)); - Thumbnail thumbnail = thumbnailRepository.save(new Thumbnail(template, sourceCode1)); - - UpdateSourceCodeRequest updateRequest1 = getUpdateSourceCodeRequest(sourceCode1); - UpdateSourceCodeRequest updateRequest2 = getUpdateSourceCodeRequest(sourceCode2); - CreateSourceCodeRequest createRequest = new CreateSourceCodeRequest("새로운 제목1", "새로운 내용1", 3); - UpdateTemplateRequest updateTemplateRequest = getUpdateTemplateRequest( - List.of(createRequest), - List.of(updateRequest1, updateRequest2), - Collections.emptyList(), - template.getCategory().getId(), - Collections.emptyList() - ); - - // when - sourceCodeService.updateSourceCodes(updateTemplateRequest, template, thumbnail); - - // then - SourceCode updatedSourceCode1 = sourceCodeRepository.fetchById(sourceCode1.getId()); - SourceCode updatedSourceCode2 = sourceCodeRepository.fetchById(sourceCode2.getId()); - SourceCode newSourceCode = sourceCodeRepository.fetchByTemplateAndOrdinal(template, 3); - - assertAll( - () -> assertThat(sourceCodeRepository.countByTemplate(template)).isEqualTo(3), - () -> assertThat(updatedSourceCode1.getFilename()).isEqualTo("변경된 제목1"), - () -> assertThat(updatedSourceCode1.getOrdinal()).isEqualTo(1), - () -> assertThat(updatedSourceCode2.getFilename()).isEqualTo("변경된 제목2"), - () -> assertThat(updatedSourceCode2.getOrdinal()).isEqualTo(2), - () -> assertThat(newSourceCode.getFilename()).isEqualTo("새로운 제목1")); - } - @Test @Disabled("애플리케이션 코드에서 로직 변경 필요") @DisplayName("성공: 일부 소스 코드 삭제 및 새로운 소스 코드 추가 시, 삭제된 코드 순서는 앞당겨지고 새로 추가된 소스 코드의 순서는 가장 마지막 순서") diff --git a/backend/src/test/java/codezap/template/service/TemplateServiceTest.java b/backend/src/test/java/codezap/template/service/TemplateServiceTest.java index 9c21c1dab..08ef8ba3b 100644 --- a/backend/src/test/java/codezap/template/service/TemplateServiceTest.java +++ b/backend/src/test/java/codezap/template/service/TemplateServiceTest.java @@ -6,6 +6,8 @@ import java.util.List; +import jakarta.persistence.EntityManager; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -38,6 +40,9 @@ class TemplateServiceTest extends ServiceTest { @Autowired private LikesService likesService; + @Autowired + private EntityManager entityManager; + @Nested @DisplayName("템플릿 생성") class CreateTemplate { @@ -191,7 +196,6 @@ private void likeTemplate(long templateId, long likesCount) { } } - @Nested @DisplayName("좋아요한 템플릿 조회") class FindAllByMemberId { @@ -212,7 +216,8 @@ void findAllByMemberId() { likesRepository.save(new Likes(template3, member1)); // when - FixedPage