diff --git a/backend/ddang/src/main/java/com/ddang/ddang/qna/application/AnswerService.java b/backend/ddang/src/main/java/com/ddang/ddang/qna/application/AnswerService.java index 2ef0967d4..17c39fdc9 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/qna/application/AnswerService.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/qna/application/AnswerService.java @@ -9,8 +9,8 @@ import com.ddang.ddang.qna.application.exception.QuestionNotFoundException; import com.ddang.ddang.qna.domain.Answer; import com.ddang.ddang.qna.domain.Question; -import com.ddang.ddang.qna.infrastructure.JpaAnswerRepository; -import com.ddang.ddang.qna.infrastructure.JpaQuestionRepository; +import com.ddang.ddang.qna.domain.repository.AnswerRepository; +import com.ddang.ddang.qna.domain.repository.QuestionRepository; import com.ddang.ddang.user.application.exception.UserNotFoundException; import com.ddang.ddang.user.domain.User; import com.ddang.ddang.user.domain.repository.UserRepository; @@ -26,8 +26,8 @@ public class AnswerService { private final ApplicationEventPublisher answerEventPublisher; private final UserRepository userRepository; - private final JpaQuestionRepository questionRepository; - private final JpaAnswerRepository answerRepository; + private final QuestionRepository questionRepository; + private final AnswerRepository answerRepository; @Transactional public Long create(final CreateAnswerDto answerDto, final String absoluteImageUrl) { @@ -65,7 +65,7 @@ private void checkAlreadyAnswered(final Question question) { @Transactional public void deleteById(final Long answerId, final Long userId) { - final Answer answer = answerRepository.findByIdAndDeletedIsFalse(answerId) + final Answer answer = answerRepository.findById(answerId) .orElseThrow(() -> new AnswerNotFoundException("해당 답변을 찾을 수 없습니다.")); final User user = userRepository.findById(userId) .orElseThrow(() -> new UserNotFoundException("해당 사용자를 찾을 수 없습니다.")); diff --git a/backend/ddang/src/main/java/com/ddang/ddang/qna/application/QuestionService.java b/backend/ddang/src/main/java/com/ddang/ddang/qna/application/QuestionService.java index 49a758758..1fb03bbf3 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/qna/application/QuestionService.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/qna/application/QuestionService.java @@ -11,11 +11,11 @@ import com.ddang.ddang.qna.application.exception.InvalidQuestionerException; import com.ddang.ddang.qna.application.exception.QuestionNotFoundException; import com.ddang.ddang.qna.domain.Question; -import com.ddang.ddang.qna.infrastructure.JpaQuestionRepository; +import com.ddang.ddang.qna.domain.repository.QuestionRepository; import com.ddang.ddang.user.application.exception.UserNotFoundException; import com.ddang.ddang.user.domain.User; -import lombok.RequiredArgsConstructor; import com.ddang.ddang.user.domain.repository.UserRepository; +import lombok.RequiredArgsConstructor; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,7 +31,7 @@ public class QuestionService { private final ApplicationEventPublisher questionEventPublisher; private final AuctionRepository auctionRepository; private final UserRepository userRepository; - private final JpaQuestionRepository questionRepository; + private final QuestionRepository questionRepository; @Transactional public Long create(final CreateQuestionDto questionDto, final String absoluteImageUrl) { diff --git a/backend/ddang/src/main/java/com/ddang/ddang/qna/application/dto/QuestionDto.java b/backend/ddang/src/main/java/com/ddang/ddang/qna/application/dto/QuestionDto.java deleted file mode 100644 index 6e5eb7224..000000000 --- a/backend/ddang/src/main/java/com/ddang/ddang/qna/application/dto/QuestionDto.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.ddang.ddang.qna.application.dto; - -import com.ddang.ddang.auction.domain.Auction; -import com.ddang.ddang.qna.domain.Answer; -import com.ddang.ddang.qna.domain.Question; -import com.ddang.ddang.user.domain.User; - -public record QuestionDto(Auction auction, User writer, String content, Answer answer, boolean deleted, String auctionImageAbsoluteUrl){ - - public static QuestionDto from(final Question question, String auctionImageAbsoluteUrl) { - return new QuestionDto( - question.getAuction(), - question.getWriter(), - question.getContent(), - question.getAnswer(), - question.isDeleted(), - auctionImageAbsoluteUrl - ); - } -} diff --git a/backend/ddang/src/main/java/com/ddang/ddang/qna/domain/repository/AnswerRepository.java b/backend/ddang/src/main/java/com/ddang/ddang/qna/domain/repository/AnswerRepository.java new file mode 100644 index 000000000..67adf0c12 --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/qna/domain/repository/AnswerRepository.java @@ -0,0 +1,14 @@ +package com.ddang.ddang.qna.domain.repository; + +import com.ddang.ddang.qna.domain.Answer; + +import java.util.Optional; + +public interface AnswerRepository { + + Answer save(final Answer answer); + + boolean existsByQuestionId(final Long questionId); + + Optional findById(final Long id); +} diff --git a/backend/ddang/src/main/java/com/ddang/ddang/qna/domain/repository/QuestionRepository.java b/backend/ddang/src/main/java/com/ddang/ddang/qna/domain/repository/QuestionRepository.java new file mode 100644 index 000000000..6da4f42bd --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/qna/domain/repository/QuestionRepository.java @@ -0,0 +1,15 @@ +package com.ddang.ddang.qna.domain.repository; + +import com.ddang.ddang.qna.domain.Question; + +import java.util.List; +import java.util.Optional; + +public interface QuestionRepository { + + Question save(final Question question); + + Optional findById(final Long id); + + List findAllByAuctionId(final Long auctionId); +} diff --git a/backend/ddang/src/main/java/com/ddang/ddang/qna/infrastructure/AnswerRepositoryImpl.java b/backend/ddang/src/main/java/com/ddang/ddang/qna/infrastructure/AnswerRepositoryImpl.java new file mode 100644 index 000000000..ed8069bfd --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/qna/infrastructure/AnswerRepositoryImpl.java @@ -0,0 +1,30 @@ +package com.ddang.ddang.qna.infrastructure; + +import com.ddang.ddang.qna.domain.Answer; +import com.ddang.ddang.qna.domain.repository.AnswerRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +@RequiredArgsConstructor +public class AnswerRepositoryImpl implements AnswerRepository { + + private final JpaAnswerRepository jpaAnswerRepository; + + @Override + public Answer save(final Answer answer) { + return jpaAnswerRepository.save(answer); + } + + @Override + public boolean existsByQuestionId(final Long questionId) { + return jpaAnswerRepository.existsByQuestionId(questionId); + } + + @Override + public Optional findById(final Long id) { + return jpaAnswerRepository.findByIdAndDeletedIsFalse(id); + } +} diff --git a/backend/ddang/src/main/java/com/ddang/ddang/qna/infrastructure/JpaAnswerRepository.java b/backend/ddang/src/main/java/com/ddang/ddang/qna/infrastructure/JpaAnswerRepository.java index eea851954..ffd0167ca 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/qna/infrastructure/JpaAnswerRepository.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/qna/infrastructure/JpaAnswerRepository.java @@ -1,8 +1,8 @@ package com.ddang.ddang.qna.infrastructure; import com.ddang.ddang.qna.domain.Answer; -import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import java.util.Optional; @@ -10,6 +10,13 @@ public interface JpaAnswerRepository extends JpaRepository { boolean existsByQuestionId(Long questionId); - @EntityGraph(attributePaths = {"question", "question.auction", "question.auction.seller"}) + @Query(""" + SELECT an + FROM Answer an + JOIN FETCH an.question q + JOIN FETCH q.auction a + JOIN FETCH a.seller + WHERE an.deleted = false AND an.id = :answerId + """) Optional findByIdAndDeletedIsFalse(final Long answerId); } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/qna/infrastructure/JpaQuestionRepository.java b/backend/ddang/src/main/java/com/ddang/ddang/qna/infrastructure/JpaQuestionRepository.java index 615e04d2b..11de78514 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/qna/infrastructure/JpaQuestionRepository.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/qna/infrastructure/JpaQuestionRepository.java @@ -1,8 +1,8 @@ package com.ddang.ddang.qna.infrastructure; import com.ddang.ddang.qna.domain.Question; -import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import java.util.List; import java.util.Optional; @@ -11,6 +11,14 @@ public interface JpaQuestionRepository extends JpaRepository { Optional findByIdAndDeletedIsFalse(final Long id); - @EntityGraph(attributePaths = {"writer", "answer", "auction", "auction.seller"}) + @Query(""" + SELECT q + FROM Question q + JOIN FETCH q.writer + LEFT JOIN FETCH q.answer + JOIN FETCH q.auction a + JOIN FETCH a.seller + WHERE q.deleted = false AND a.id = :auctionId + """) List findAllByAuctionId(final Long auctionId); } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/qna/infrastructure/QuestionRepositoryImpl.java b/backend/ddang/src/main/java/com/ddang/ddang/qna/infrastructure/QuestionRepositoryImpl.java new file mode 100644 index 000000000..fd107d99a --- /dev/null +++ b/backend/ddang/src/main/java/com/ddang/ddang/qna/infrastructure/QuestionRepositoryImpl.java @@ -0,0 +1,31 @@ +package com.ddang.ddang.qna.infrastructure; + +import com.ddang.ddang.qna.domain.Question; +import com.ddang.ddang.qna.domain.repository.QuestionRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +@Repository +@RequiredArgsConstructor +public class QuestionRepositoryImpl implements QuestionRepository { + + private final JpaQuestionRepository jpaQuestionRepository; + + @Override + public Question save(final Question question) { + return jpaQuestionRepository.save(question); + } + + @Override + public Optional findById(final Long id) { + return jpaQuestionRepository.findByIdAndDeletedIsFalse(id); + } + + @Override + public List findAllByAuctionId(final Long auctionId) { + return jpaQuestionRepository.findAllByAuctionId(auctionId); + } +} diff --git a/backend/ddang/src/main/java/com/ddang/ddang/report/application/AnswerReportService.java b/backend/ddang/src/main/java/com/ddang/ddang/report/application/AnswerReportService.java index 77e48aa98..ed67037e7 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/report/application/AnswerReportService.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/report/application/AnswerReportService.java @@ -2,7 +2,7 @@ import com.ddang.ddang.qna.application.exception.AnswerNotFoundException; import com.ddang.ddang.qna.domain.Answer; -import com.ddang.ddang.qna.infrastructure.JpaAnswerRepository; +import com.ddang.ddang.qna.domain.repository.AnswerRepository; import com.ddang.ddang.report.application.dto.CreateAnswerReportDto; import com.ddang.ddang.report.application.dto.ReadAnswerReportDto; import com.ddang.ddang.report.application.exception.InvalidAnswererReportException; @@ -22,13 +22,13 @@ @RequiredArgsConstructor public class AnswerReportService { - private final JpaAnswerRepository answerRepository; + private final AnswerRepository answerRepository; private final UserRepository userRepository; private final AnswerReportRepository answerReportRepository; @Transactional public Long create(final CreateAnswerReportDto answerReportDto) { - final Answer answer = answerRepository.findByIdAndDeletedIsFalse(answerReportDto.answerId()) + final Answer answer = answerRepository.findById(answerReportDto.answerId()) .orElseThrow(() -> new AnswerNotFoundException("해당 답변을 찾을 수 없습니다.") ); diff --git a/backend/ddang/src/main/java/com/ddang/ddang/report/application/QuestionReportService.java b/backend/ddang/src/main/java/com/ddang/ddang/report/application/QuestionReportService.java index e9194ea4a..f47825c45 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/report/application/QuestionReportService.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/report/application/QuestionReportService.java @@ -2,7 +2,7 @@ import com.ddang.ddang.qna.application.exception.QuestionNotFoundException; import com.ddang.ddang.qna.domain.Question; -import com.ddang.ddang.qna.infrastructure.JpaQuestionRepository; +import com.ddang.ddang.qna.domain.repository.QuestionRepository; import com.ddang.ddang.report.application.dto.CreateQuestionReportDto; import com.ddang.ddang.report.application.dto.ReadQuestionReportDto; import com.ddang.ddang.report.application.exception.InvalidQuestionReportException; @@ -22,13 +22,13 @@ @RequiredArgsConstructor public class QuestionReportService { - private final JpaQuestionRepository questionRepository; + private final QuestionRepository questionRepository; private final UserRepository userRepository; private final QuestionReportRepository questionReportRepository; @Transactional public Long create(final CreateQuestionReportDto questionReportDto) { - final Question question = questionRepository.findByIdAndDeletedIsFalse(questionReportDto.questionId()) + final Question question = questionRepository.findById(questionReportDto.questionId()) .orElseThrow(() -> new QuestionNotFoundException("해당 질문을 찾을 수 없습니다.") ); diff --git a/backend/ddang/src/test/java/com/ddang/ddang/qna/application/fixture/AnswerServiceFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/qna/application/fixture/AnswerServiceFixture.java index 0cb19e684..11ac6f45c 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/qna/application/fixture/AnswerServiceFixture.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/qna/application/fixture/AnswerServiceFixture.java @@ -8,8 +8,8 @@ import com.ddang.ddang.qna.application.dto.CreateAnswerDto; import com.ddang.ddang.qna.domain.Answer; import com.ddang.ddang.qna.domain.Question; -import com.ddang.ddang.qna.infrastructure.JpaAnswerRepository; -import com.ddang.ddang.qna.infrastructure.JpaQuestionRepository; +import com.ddang.ddang.qna.domain.repository.AnswerRepository; +import com.ddang.ddang.qna.domain.repository.QuestionRepository; import com.ddang.ddang.user.domain.Reliability; import com.ddang.ddang.user.domain.User; import com.ddang.ddang.user.domain.repository.UserRepository; @@ -17,7 +17,6 @@ import org.springframework.beans.factory.annotation.Autowired; import java.time.LocalDateTime; -import java.util.List; @SuppressWarnings("NonAsciiCharacters") public class AnswerServiceFixture { @@ -29,10 +28,10 @@ public class AnswerServiceFixture { private UserRepository userRepository; @Autowired - private JpaQuestionRepository questionRepository; + private QuestionRepository questionRepository; @Autowired - private JpaAnswerRepository answerRepository; + private AnswerRepository answerRepository; protected Long 존재하지_않는_답변_아이디 = -999L; protected Long 존재하지_않는_사용자_아이디 = -999L; @@ -87,7 +86,8 @@ void setUp() { userRepository.save(판매자가_아닌_사용자); auctionRepository.save(경매); - questionRepository.saveAll(List.of(질문, 답변한_질문)); + questionRepository.save(질문); + questionRepository.save(답변한_질문); answerRepository.save(답변); 답변_등록_요청_dto = new CreateAnswerDto(질문.getId(), "답변 드립니다.", 판매자.getId()); diff --git a/backend/ddang/src/test/java/com/ddang/ddang/qna/application/fixture/QuestionServiceFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/qna/application/fixture/QuestionServiceFixture.java index 63818f386..ac73432f8 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/qna/application/fixture/QuestionServiceFixture.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/qna/application/fixture/QuestionServiceFixture.java @@ -13,8 +13,8 @@ import com.ddang.ddang.qna.application.dto.ReadUserInQnaDto; import com.ddang.ddang.qna.domain.Answer; import com.ddang.ddang.qna.domain.Question; -import com.ddang.ddang.qna.infrastructure.JpaAnswerRepository; -import com.ddang.ddang.qna.infrastructure.JpaQuestionRepository; +import com.ddang.ddang.qna.domain.repository.AnswerRepository; +import com.ddang.ddang.qna.domain.repository.QuestionRepository; import com.ddang.ddang.region.domain.Region; import com.ddang.ddang.region.domain.repository.RegionRepository; import com.ddang.ddang.user.domain.Reliability; @@ -24,7 +24,6 @@ import org.springframework.beans.factory.annotation.Autowired; import java.time.LocalDateTime; -import java.util.List; @SuppressWarnings("NonAsciiCharacters") public class QuestionServiceFixture { @@ -36,10 +35,10 @@ public class QuestionServiceFixture { private AuctionRepository auctionRepository; @Autowired - private JpaQuestionRepository questionRepository; + private QuestionRepository questionRepository; @Autowired - private JpaAnswerRepository answerRepository; + private AnswerRepository answerRepository; @Autowired private RegionRepository regionRepository; @@ -166,8 +165,11 @@ void setUp() { auctionRepository.save(질문과_답변이_존재하는_경매); auctionRepository.save(종료된_경매); auctionRepository.save(삭제된_경매); - questionRepository.saveAll(List.of(질문, 질문2, 질문3)); - answerRepository.saveAll(List.of(답변1, 답변2)); + questionRepository.save(질문); + questionRepository.save(질문2); + questionRepository.save(질문3); + answerRepository.save(답변1); + answerRepository.save(답변2); 질문_3개_답변_2개가_존재하는_경매_아이디 = 질문과_답변이_존재하는_경매.getId(); diff --git a/backend/ddang/src/test/java/com/ddang/ddang/qna/infrastructure/AnswerRepositoryImplTest.java b/backend/ddang/src/test/java/com/ddang/ddang/qna/infrastructure/AnswerRepositoryImplTest.java new file mode 100644 index 000000000..8d516216b --- /dev/null +++ b/backend/ddang/src/test/java/com/ddang/ddang/qna/infrastructure/AnswerRepositoryImplTest.java @@ -0,0 +1,81 @@ +package com.ddang.ddang.qna.infrastructure; + +import com.ddang.ddang.configuration.JpaConfiguration; +import com.ddang.ddang.configuration.QuerydslConfiguration; +import com.ddang.ddang.qna.domain.Answer; +import com.ddang.ddang.qna.domain.repository.AnswerRepository; +import com.ddang.ddang.qna.infrastructure.fixture.AnswerRepositoryImplFixture; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaTest +@Import({JpaConfiguration.class, QuerydslConfiguration.class}) +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class AnswerRepositoryImplTest extends AnswerRepositoryImplFixture { + + AnswerRepository answerRepository; + + @BeforeEach + void setUp(@Autowired final JpaAnswerRepository jpaAnswerRepository) { + answerRepository = new AnswerRepositoryImpl(jpaAnswerRepository); + } + + @Test + void 답변을_저장한다() { + // given + final Answer answer = new Answer(답변_내용); + 질문.addAnswer(answer); + + // when + final Answer actual = answerRepository.save(answer); + + // then + assertThat(actual.getId()).isPositive(); + } + + @Test + void 이미_질문에_대한_답변이_존재한다면_참을_반환한다() { + // when + final boolean actual = answerRepository.existsByQuestionId(답변이_존재하는_질문.getId()); + + // then + assertThat(actual).isTrue(); + } + + @Test + void 이미_질문에_대한_답변이_존재하지_않는다면_거짓을_반환한다() { + // when + final boolean actual = answerRepository.existsByQuestionId(답변이_존재하지_않는_질문.getId()); + + // then + assertThat(actual).isFalse(); + } + + @Test + void 삭제된_답변은_조회되지_않는다() { + // when + final Optional actual = answerRepository.findById(삭제된_답변.getId()); + + // then + assertThat(actual).isEmpty(); + } + + @Test + void 삭제되지_않은_답변은_조회된다() { + // when + final Optional actual = answerRepository.findById(답변.getId()); + + // then + assertThat(actual).contains(답변); + } +} diff --git a/backend/ddang/src/test/java/com/ddang/ddang/qna/infrastructure/QuestionRepositoryImplTest.java b/backend/ddang/src/test/java/com/ddang/ddang/qna/infrastructure/QuestionRepositoryImplTest.java new file mode 100644 index 000000000..f3522af97 --- /dev/null +++ b/backend/ddang/src/test/java/com/ddang/ddang/qna/infrastructure/QuestionRepositoryImplTest.java @@ -0,0 +1,81 @@ +package com.ddang.ddang.qna.infrastructure; + +import com.ddang.ddang.configuration.JpaConfiguration; +import com.ddang.ddang.configuration.QuerydslConfiguration; +import com.ddang.ddang.qna.domain.Question; +import com.ddang.ddang.qna.domain.repository.QuestionRepository; +import com.ddang.ddang.qna.infrastructure.fixture.QuestionRepositoryImplFixture; +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaTest +@Import({JpaConfiguration.class, QuerydslConfiguration.class}) +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class QuestionRepositoryImplTest extends QuestionRepositoryImplFixture { + + QuestionRepository questionRepository; + + @BeforeEach + void setUp(@Autowired final JpaQuestionRepository jpaQuestionRepository) { + questionRepository = new QuestionRepositoryImpl(jpaQuestionRepository); + } + + @Test + void 질문을_저장한다() { + // given + final Question question = new Question(경매, 질문자, 질문_내용); + + // when + final Question actual = questionRepository.save(question); + + // then + assertThat(actual.getId()).isPositive(); + } + + @Test + void 삭제된_질문은_조회되지_않는다() { + // when + final Optional actual = questionRepository.findById(삭제된_질문.getId()); + + // then + assertThat(actual).isEmpty(); + } + + @Test + void 삭제되지_않은_질문은_조회된다() { + // when + final Optional actual = questionRepository.findById(질문1.getId()); + + // then + assertThat(actual).contains(질문1); + } + + @Test + void 경매_아이디를_통해_질문과_답변들을_모두_조회한다() { + // when + final List actual = questionRepository.findAllByAuctionId(질문이_3개_답변이_2개인_경매.getId()); + + // then + SoftAssertions.assertSoftly(softAssertions -> { + softAssertions.assertThat(actual).hasSize(3); + softAssertions.assertThat(actual.get(0)).isEqualTo(질문1); + softAssertions.assertThat(actual.get(0).getAnswer()).isEqualTo(답변1); + softAssertions.assertThat(actual.get(1)).isEqualTo(질문2); + softAssertions.assertThat(actual.get(1).getAnswer()).isEqualTo(답변2); + softAssertions.assertThat(actual.get(2)).isEqualTo(질문3); + softAssertions.assertThat(actual.get(2).getAnswer()).isNull(); + }); + } +} diff --git a/backend/ddang/src/test/java/com/ddang/ddang/qna/infrastructure/fixture/AnswerRepositoryImplFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/qna/infrastructure/fixture/AnswerRepositoryImplFixture.java new file mode 100644 index 000000000..44cac6457 --- /dev/null +++ b/backend/ddang/src/test/java/com/ddang/ddang/qna/infrastructure/fixture/AnswerRepositoryImplFixture.java @@ -0,0 +1,102 @@ +package com.ddang.ddang.qna.infrastructure.fixture; + +import com.ddang.ddang.auction.domain.Auction; +import com.ddang.ddang.auction.domain.BidUnit; +import com.ddang.ddang.auction.domain.Price; +import com.ddang.ddang.auction.domain.repository.AuctionRepository; +import com.ddang.ddang.auction.infrastructure.persistence.AuctionRepositoryImpl; +import com.ddang.ddang.auction.infrastructure.persistence.JpaAuctionRepository; +import com.ddang.ddang.auction.infrastructure.persistence.QuerydslAuctionRepository; +import com.ddang.ddang.image.domain.ProfileImage; +import com.ddang.ddang.qna.domain.Answer; +import com.ddang.ddang.qna.domain.Question; +import com.ddang.ddang.qna.domain.repository.AnswerRepository; +import com.ddang.ddang.qna.domain.repository.QuestionRepository; +import com.ddang.ddang.qna.infrastructure.AnswerRepositoryImpl; +import com.ddang.ddang.qna.infrastructure.JpaAnswerRepository; +import com.ddang.ddang.qna.infrastructure.JpaQuestionRepository; +import com.ddang.ddang.qna.infrastructure.QuestionRepositoryImpl; +import com.ddang.ddang.user.domain.Reliability; +import com.ddang.ddang.user.domain.User; +import com.ddang.ddang.user.domain.repository.UserRepository; +import com.ddang.ddang.user.infrastructure.persistence.JpaUserRepository; +import com.ddang.ddang.user.infrastructure.persistence.UserRepositoryImpl; +import com.querydsl.jpa.impl.JPAQueryFactory; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDateTime; + +@SuppressWarnings("NonAsciiCharacters") +public class AnswerRepositoryImplFixture { + + private UserRepository userRepository; + + private AuctionRepository auctionRepository; + + private QuestionRepository questionRepository; + + private AnswerRepository answerRepository; + + protected Question 질문; + protected Question 답변이_존재하는_질문; + protected Question 답변이_존재하지_않는_질문; + protected String 답변_내용 = "답변드립니다."; + protected Answer 답변; + protected Answer 삭제된_답변; + + @BeforeEach + void setUpFixture( + @Autowired final JpaUserRepository jpaUserRepository, + @Autowired final JpaAuctionRepository jpaAuctionRepository, + @Autowired final JPAQueryFactory queryFactory, + @Autowired final JpaQuestionRepository jpaQuestionRepository, + @Autowired final JpaAnswerRepository jpaAnswerRepository + ) { + userRepository = new UserRepositoryImpl(jpaUserRepository); + auctionRepository = new AuctionRepositoryImpl(jpaAuctionRepository, new QuerydslAuctionRepository(queryFactory)); + questionRepository = new QuestionRepositoryImpl(jpaQuestionRepository); + answerRepository = new AnswerRepositoryImpl(jpaAnswerRepository); + + final ProfileImage 프로필_이미지 = new ProfileImage("프로필.jpg", "프로필.jpg"); + final User 판매자 = User.builder() + .name("판매자") + .profileImage(프로필_이미지) + .reliability(new Reliability(4.7d)) + .oauthId("12345") + .build(); + final Auction 경매 = Auction.builder() + .seller(판매자) + .title("경매 상품 1") + .description("이것은 경매 상품 1 입니다.") + .bidUnit(new BidUnit(1_000)) + .startPrice(new Price(1_000)) + .closingTime(LocalDateTime.now()) + .build(); + final User 질문자 = User.builder() + .name("질문자") + .profileImage(프로필_이미지) + .reliability(new Reliability(4.7d)) + .oauthId("12346") + .build(); + 질문 = new Question(경매, 질문자, "궁금한 점이 있어요."); + 답변이_존재하는_질문 = new Question(경매, 질문자, "궁금한 점이 있어요."); + 답변이_존재하지_않는_질문 = 질문; + final Question 답변이_삭제된_질문 = new Question(경매, 질문자, "궁금한 점이 있어요."); + + 답변 = new Answer("답변드립니다."); + 답변이_존재하는_질문.addAnswer(답변); + 삭제된_답변 = new Answer("답변드립니다."); + 답변이_삭제된_질문.addAnswer(삭제된_답변); + 삭제된_답변.delete(); + + userRepository.save(판매자); + userRepository.save(질문자); + auctionRepository.save(경매); + questionRepository.save(질문); + questionRepository.save(답변이_존재하는_질문); + questionRepository.save(답변이_삭제된_질문); + answerRepository.save(답변); + answerRepository.save(삭제된_답변); + } +} diff --git a/backend/ddang/src/test/java/com/ddang/ddang/qna/infrastructure/fixture/QuestionRepositoryImplFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/qna/infrastructure/fixture/QuestionRepositoryImplFixture.java new file mode 100644 index 000000000..f0bb5e568 --- /dev/null +++ b/backend/ddang/src/test/java/com/ddang/ddang/qna/infrastructure/fixture/QuestionRepositoryImplFixture.java @@ -0,0 +1,117 @@ +package com.ddang.ddang.qna.infrastructure.fixture; + +import com.ddang.ddang.auction.domain.Auction; +import com.ddang.ddang.auction.domain.BidUnit; +import com.ddang.ddang.auction.domain.Price; +import com.ddang.ddang.auction.domain.repository.AuctionRepository; +import com.ddang.ddang.auction.infrastructure.persistence.AuctionRepositoryImpl; +import com.ddang.ddang.auction.infrastructure.persistence.JpaAuctionRepository; +import com.ddang.ddang.auction.infrastructure.persistence.QuerydslAuctionRepository; +import com.ddang.ddang.image.domain.ProfileImage; +import com.ddang.ddang.qna.domain.Answer; +import com.ddang.ddang.qna.domain.Question; +import com.ddang.ddang.qna.domain.repository.AnswerRepository; +import com.ddang.ddang.qna.domain.repository.QuestionRepository; +import com.ddang.ddang.qna.infrastructure.AnswerRepositoryImpl; +import com.ddang.ddang.qna.infrastructure.JpaAnswerRepository; +import com.ddang.ddang.qna.infrastructure.JpaQuestionRepository; +import com.ddang.ddang.qna.infrastructure.QuestionRepositoryImpl; +import com.ddang.ddang.user.domain.Reliability; +import com.ddang.ddang.user.domain.User; +import com.ddang.ddang.user.domain.repository.UserRepository; +import com.ddang.ddang.user.infrastructure.persistence.JpaUserRepository; +import com.ddang.ddang.user.infrastructure.persistence.UserRepositoryImpl; +import com.querydsl.jpa.impl.JPAQueryFactory; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDateTime; + +@SuppressWarnings("NonAsciiCharacters") +public class QuestionRepositoryImplFixture { + + private AuctionRepository auctionRepository; + + private UserRepository userRepository; + + private QuestionRepository questionRepository; + + private AnswerRepository answerRepository; + + protected Auction 경매; + protected Auction 질문이_3개_답변이_2개인_경매; + protected User 질문자; + protected String 질문_내용 = "궁금한 점이 있어요."; + protected Question 질문1; + protected Question 질문2; + protected Question 질문3; + protected Question 삭제된_질문; + protected Answer 답변1; + protected Answer 답변2; + + @BeforeEach + void setUpFixture( + @Autowired final JpaAuctionRepository jpaAuctionRepository, + @Autowired final JPAQueryFactory queryFactory, + @Autowired final JpaUserRepository jpaUserRepository, + @Autowired final JpaQuestionRepository jpaQuestionRepository, + @Autowired final JpaAnswerRepository jpaAnswerRepository + ) { + auctionRepository = new AuctionRepositoryImpl(jpaAuctionRepository, new QuerydslAuctionRepository(queryFactory)); + userRepository = new UserRepositoryImpl(jpaUserRepository); + questionRepository = new QuestionRepositoryImpl(jpaQuestionRepository); + answerRepository = new AnswerRepositoryImpl(jpaAnswerRepository); + + final ProfileImage 프로필_이미지 = new ProfileImage("프로필.jpg", "프로필.jpg"); + final User 판매자 = User.builder() + .name("판매자") + .profileImage(프로필_이미지) + .reliability(new Reliability(4.7d)) + .oauthId("12345") + .build(); + 경매 = Auction.builder() + .seller(판매자) + .title("경매 상품") + .description("이것은 경매 상품입니다.") + .bidUnit(new BidUnit(1_000)) + .startPrice(new Price(1_000)) + .closingTime(LocalDateTime.now()) + .build(); + 질문이_3개_답변이_2개인_경매 = Auction.builder() + .seller(판매자) + .title("경매 상품") + .description("이것은 경매 상품입니다.") + .bidUnit(new BidUnit(1_000)) + .startPrice(new Price(1_000)) + .closingTime(LocalDateTime.now()) + .build(); + 질문자 = User.builder() + .name("질문자") + .profileImage(프로필_이미지) + .reliability(new Reliability(4.7d)) + .oauthId("12346") + .build(); + + 질문1 = new Question(질문이_3개_답변이_2개인_경매, 질문자, "질문1"); + 질문2 = new Question(질문이_3개_답변이_2개인_경매, 질문자, "질문2"); + 질문3 = new Question(질문이_3개_답변이_2개인_경매, 질문자, "질문3"); + 답변1 = new Answer("답변1"); + 답변2 = new Answer("답변2"); + 질문1.addAnswer(답변1); + 질문2.addAnswer(답변2); + + 삭제된_질문 = new Question(경매, 질문자, "질문3"); + 삭제된_질문.delete(); + + userRepository.save(판매자); + userRepository.save(질문자); + auctionRepository.save(경매); + auctionRepository.save(질문이_3개_답변이_2개인_경매); + questionRepository.save(질문1); + questionRepository.save(질문2); + questionRepository.save(질문3); + questionRepository.save(삭제된_질문); + answerRepository.save(답변1); + answerRepository.save(답변2); + } +} diff --git a/backend/ddang/src/test/java/com/ddang/ddang/report/application/fixture/AnswerReportServiceFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/report/application/fixture/AnswerReportServiceFixture.java index dfdd32d84..dbb98a243 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/report/application/fixture/AnswerReportServiceFixture.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/report/application/fixture/AnswerReportServiceFixture.java @@ -10,8 +10,8 @@ import com.ddang.ddang.image.domain.ProfileImage; import com.ddang.ddang.qna.domain.Answer; import com.ddang.ddang.qna.domain.Question; -import com.ddang.ddang.qna.infrastructure.JpaAnswerRepository; -import com.ddang.ddang.qna.infrastructure.JpaQuestionRepository; +import com.ddang.ddang.qna.domain.repository.AnswerRepository; +import com.ddang.ddang.qna.domain.repository.QuestionRepository; import com.ddang.ddang.report.application.dto.CreateAnswerReportDto; import com.ddang.ddang.report.domain.AnswerReport; import com.ddang.ddang.report.domain.repository.AnswerReportRepository; @@ -37,10 +37,10 @@ public class AnswerReportServiceFixture { private AuctionRepository auctionRepository; @Autowired - private JpaQuestionRepository questionRepository; + private QuestionRepository questionRepository; @Autowired - private JpaAnswerRepository answerRepository; + private AnswerRepository answerRepository; @Autowired private AnswerReportRepository answerReportRepository; diff --git a/backend/ddang/src/test/java/com/ddang/ddang/report/application/fixture/QuestionReportServiceFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/report/application/fixture/QuestionReportServiceFixture.java index 9e671032c..7e7bb9d8e 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/report/application/fixture/QuestionReportServiceFixture.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/report/application/fixture/QuestionReportServiceFixture.java @@ -9,7 +9,7 @@ import com.ddang.ddang.image.domain.AuctionImage; import com.ddang.ddang.image.domain.ProfileImage; import com.ddang.ddang.qna.domain.Question; -import com.ddang.ddang.qna.infrastructure.JpaQuestionRepository; +import com.ddang.ddang.qna.domain.repository.QuestionRepository; import com.ddang.ddang.report.application.dto.CreateQuestionReportDto; import com.ddang.ddang.report.domain.QuestionReport; import com.ddang.ddang.report.domain.repository.QuestionReportRepository; @@ -35,7 +35,7 @@ public class QuestionReportServiceFixture { private AuctionRepository auctionRepository; @Autowired - private JpaQuestionRepository questionRepository; + private QuestionRepository questionRepository; @Autowired private QuestionReportRepository questionReportRepository;