[ClassFlix] EP 4. domain, repository, service 계층별 설계 및 구현
Project/ClassFlix

[ClassFlix] EP 4. domain, repository, service 계층별 설계 및 구현

목차 (클릭시 해당 목차로 이동)


     

     

    * 현재 작성한 코드 기준이며 언제든지 코드는 바뀔 수 있습니다.

    바뀐 코드는 아래 깃허브 주소에서 보실 수 있습니다.

    github.com/dongho108/ClassFlix/tree/develop

     

    dongho108/ClassFlix

    회원등록, 강의정보등록, 후기등록이 가능한 웹사이트를 구축합니다. Contribute to dongho108/ClassFlix development by creating an account on GitHub.

    github.com

     

     

     

    도메인

     

    Member

     

    설계

    Long id @Id, @GeneratedValue, @Column
    String username 필수 o
    int age 필수 o
    Gender gender 필수 o
    String career 필수 x
    List<Review> reviews @OneToMany
         

     

    코드

    package dongho.classflix.domain;
    
    import lombok.Getter;
    
    import javax.persistence.*;
    import javax.validation.constraints.NotEmpty;
    
    import java.util.ArrayList;
    import java.util.List;
    
    @Entity
    @Getter
    public class Member {
        @Id
        @GeneratedValue
        @Column(name = "member_id")
        private Long id;
    
        private String userName;
    
        private int age;
    
        @Enumerated(EnumType.STRING)
        private Gender gender;
    
        private String career;
    
        @OneToMany(mappedBy = "member")
        private List<Review> reviews = new ArrayList<>();
    
        protected Member() {
        }
    
        public Member(String userName, int age, Gender gender) {
            this.userName = userName;
            this.age = age;
            this.gender = gender;
        }
    
        public Member(String userName, int age, Gender gender, String career) {
            this.userName = userName;
            this.age = age;
            this.gender = gender;
            this.career = career;
        }
    }
    

     

    • 필수인 것들을 저장하는 생성자와 필수가 아닌 것들도 저장하는 생성자 두개
      (나중에 실제로 쓰이는지 확인 후 수정 필요)

     

     

     

    Lecture

    설계

    Long id @Id, @GeneraedValue
    String lectureName 필수 o
    String teacherName 필수 o
    String content 필수 o
    byte[] representImage 필수 x
    String siteName 필수 x
    URI uri 필수 x
    double averageRating  
    int reviewNum  
    List<Review> reviews @OneToMany, cascade

     

    • lecture에 reivew 추가 로직
    • lecture에 reivew 삭제 로직
    • 평균 리뷰 별점 계산 로직
    • 강의 수정을 위한 change로직
    • 필수, 필수 아닌것들 생성자 따로 (후에 수정 필요할지도)

     

     

     

    코드

    package dongho.classflix.domain;
    
    import lombok.Getter;
    
    import javax.persistence.*;
    import javax.validation.constraints.NotEmpty;
    import java.awt.*;
    import java.net.URI;
    import java.time.LocalDateTime;
    import java.util.ArrayList;
    import java.util.List;
    
    import static javax.persistence.CascadeType.*;
    
    @Entity
    @Getter
    public class Lecture {
    
        @Id
        @GeneratedValue
        @Column(name = "lecture_id")
        private Long id;
    
        private String lectureName;
    
        private String teacherName;
    
        private String content;
    
        private byte[] representImage;
        private String siteName;
        private URI uri;
        private LocalDateTime lectureDateTime;
    
        private double averageRating;
        private int reviewNum;
    
        @OneToMany(mappedBy = "lecture", cascade = ALL)
        private List<Review> reviews = new ArrayList<>();
    
        protected Lecture() {
        }
    
        public Lecture(String lectureName, String teacherName, String content, LocalDateTime lectureDateTime) {
            this.lectureName = lectureName;
            this.teacherName = teacherName;
            this.content = content;
            this.lectureDateTime = lectureDateTime;
        }
    
        public Lecture(String lectureName, String teacherName, String content, byte[] representImage, String siteName, URI uri) {
            this.lectureName = lectureName;
            this.teacherName = teacherName;
            this.content = content;
            this.representImage = representImage;
            this.siteName = siteName;
            this.uri = uri;
        }
    
        public void addReview(Integer rating) {
            this.reviewNum += 1;
            updateAverageRating(rating);
        }
    
        public void removeReview(Integer rating) {
            int restReview = this.reviewNum - 1;
            if (restReview < 0) {
                throw new NotEnoughReviewException("review is empty");
            }
            this.reviewNum -= 1;
            updateAverageRating(rating);
        }
    
        public void updateAverageRating(Integer rating) {
            if (reviewNum == 0) {
                this.averageRating = 0;
            } else {
                double average = (averageRating + rating) / reviewNum;
                this.averageRating = Math.floor(average);
            }
        }
    
        public void changeLectureData(String lectureName, String teacherName, String content, byte[] representImage, String siteName, URI uri) {
            this.lectureName = lectureName;
            this.teacherName = teacherName;
            this.content = content;
            this.representImage = representImage;
            this.siteName = siteName;
            this.uri = uri;
        }
    
    }
    

     

     

    테스트코드

    package dongho.classflix.domain;
    
    import org.assertj.core.api.Assertions;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.persistence.EntityManager;
    
    import java.time.LocalDateTime;
    
    import static org.junit.jupiter.api.Assertions.*;
    
    @SpringBootTest
    @Transactional
    class LectureTest {
    
        @Autowired
        EntityManager em;
    
        // 리뷰 개수와 평균별점
        @Test
        public void 강의의리뷰개수추가() throws Exception {
            //given
            Member member = new Member("dongho", 25, Gender.MALE);
            em.persist(member);
    
            Lecture lecture = new Lecture("jpa", "김영한", "jpa강의", LocalDateTime.now());
            em.persist(lecture);
    
            Review review1 = new Review(member, "1234", "good", 4, lecture, LocalDateTime.now());
            em.persist(review1);
    
            Review review2 = new Review(member, "1234", "bad", 1, lecture, LocalDateTime.now());
            em.persist(review2);
    
    
            //when
            lecture.addReview(review1.getRating());
            lecture.addReview(review2.getRating());
    
            //then
            Assertions.assertThat(lecture.getReviewNum()).isEqualTo(2);
    
        }
    
        @Test
        public void 강의의리뷰개수감소() throws Exception {
            //given
            Member member = new Member("dongho", 25, Gender.MALE);
            em.persist(member);
    
            Lecture lecture = new Lecture("jpa", "김영한", "jpa강의", LocalDateTime.now());
            em.persist(lecture);
    
            Review review1 = new Review(member, "1234", "good", 4, lecture, LocalDateTime.now());
            em.persist(review1);
    
            Review review2 = new Review(member, "1234", "bad", 1, lecture, LocalDateTime.now());
            em.persist(review2);
    
    
            //when
            lecture.addReview(review1.getRating());
            lecture.addReview(review2.getRating());
            lecture.removeReview(review1.getRating());
            lecture.removeReview(review2.getRating());
    
            //then
            Assertions.assertThat(lecture.getReviewNum()).isEqualTo(0);
    
            assertThrows(NotEnoughReviewException.class, () -> {
                lecture.removeReview(1);
            });
    
        }
    
        @Test
        public void 강의평균별점() throws Exception {
            //given
            Member member = new Member("dongho", 25, Gender.MALE);
            em.persist(member);
    
            Lecture lecture = new Lecture("jpa", "김영한", "jpa강의", LocalDateTime.now());
            em.persist(lecture);
    
            Review review1 = new Review(member, "1234", "good", 4, lecture, LocalDateTime.now());
            em.persist(review1);
    
            Review review2 = new Review(member, "1234", "bad", 1, lecture, LocalDateTime.now());
            em.persist(review2);
    
    
            //when
            lecture.addReview(review1.getRating());
            lecture.addReview(review2.getRating());
    
            //then
            Assertions.assertThat(lecture.getAverageRating()).isEqualTo(2);
        }
    
    
    }

     

     

     

    Review

    설계

    Long id @Id, @GeneraedValue
    Member member @ManyToOne
    String password  
    String content  
    Integer rating  
    Lecture lecture @ManyToOne
    LocalDateTime reviewDate  

     

    • 리뷰수정이 가능하도록 content, rating 수정 메소드

     

     

    코드

    package dongho.classflix.domain;
    
    import lombok.Getter;
    
    import javax.persistence.*;
    import javax.swing.*;
    import javax.validation.constraints.NotEmpty;
    import java.time.LocalDateTime;
    import static javax.persistence.FetchType.*;
    
    @Entity
    @Getter
    public class Review {
    
        @Id
        @GeneratedValue
        @Column(name = "review_id")
        private Long id;
    
        @ManyToOne(fetch = LAZY)
        @JoinColumn(name = "member_id")
        private Member member;
    
        private String password;
    
        private String content;
    
        private Integer rating;
    
        @ManyToOne(fetch = LAZY)
        @JoinColumn(name = "lecture_id")
        private Lecture lecture;
    
        private LocalDateTime reviewDate;
    
        protected Review() {
        }
    
        public Review(Member member, String password, String content, Integer rating, Lecture lecture, LocalDateTime reviewDate) {
            this.member = member;
            this.password = password;
            this.content = content;
            this.rating = rating;
            this.lecture = lecture;
            this.reviewDate = reviewDate;
        }
    
        public void changeContentAndRating(String content, Integer rating) {
            this.content = content;
            this.rating = rating;
        }
    }
    

     

     

     

     

     

    리포지토리

    Member

    설계

     

    • 회원등록
    • 회원 Id로 조회
    • 회원 이름으로 조회 -> 검색, 중복확인용
    • 회원 전부 조회

    코드

    package dongho.classflix.repository;
    
    import dongho.classflix.domain.Member;
    import lombok.RequiredArgsConstructor;
    import org.springframework.stereotype.Repository;
    
    import javax.persistence.EntityManager;
    import java.util.List;
    
    @Repository
    @RequiredArgsConstructor
    public class MemberRepository {
        private final EntityManager em;
    
        // 회원등록
        public Long save(Member member) {
            em.persist(member);
            return member.getId();
        }
    
        // 회원 조회
        public Member findById(Long id) {
            return em.find(Member.class, id);
        }
    
        public List<Member> findByName(String name) {
            return em.createQuery("select m from Member m where m.userName = :name", Member.class)
                    .setParameter("name", name)
                    .getResultList();
        }
    
        public List<Member> findAll() {
            return em.createQuery("select m from Member m", Member.class)
                    .getResultList();
        }
    
    }
    

     

    테스트코드

    package dongho.classflix.repository;
    
    import dongho.classflix.domain.Gender;
    import dongho.classflix.domain.Member;
    import org.assertj.core.api.Assertions;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.persistence.EntityManager;
    
    @SpringBootTest
    @Transactional
    class MemberRepositoryTest {
    
        @Autowired
        MemberRepository memberRepository;
    
        @Autowired
        EntityManager em;
    
        @Test
        public void 회원등록() throws Exception {
            //given
            Member member = new Member("dongho", 25, Gender.MALE);
    
            //when
            Long savedId = memberRepository.save(member);
    
            //then
            Assertions.assertThat(member).isEqualTo(memberRepository.findById(savedId));
        }
    }

     

    테스트코드

    package dongho.classflix.repository;
    
    import dongho.classflix.domain.Gender;
    import dongho.classflix.domain.Member;
    import org.assertj.core.api.Assertions;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.persistence.EntityManager;
    
    @SpringBootTest
    @Transactional
    class MemberRepositoryTest {
    
        @Autowired
        MemberRepository memberRepository;
    
        @Autowired
        EntityManager em;
    
        @Test
        public void 회원등록() throws Exception {
            //given
            Member member = new Member("dongho", 25, Gender.MALE);
    
            //when
            Long savedId = memberRepository.save(member);
    
            //then
            Assertions.assertThat(member).isEqualTo(memberRepository.findById(savedId));
        }
    }

     

     

     

    Lecture

    설계

     

    • 강의 등록
    • 강의 Id 조회
    • 강의 이름 조회 -> 검색, 중복확인용
    • 강의 전체 조회

    코드

     

    package dongho.classflix.repository;
    
    import dongho.classflix.domain.Lecture;
    import lombok.RequiredArgsConstructor;
    import org.springframework.stereotype.Repository;
    
    import javax.persistence.EntityManager;
    import java.util.List;
    
    @Repository
    @RequiredArgsConstructor
    public class LectureRepository {
    
        private final EntityManager em;
    
    
        // 강의 등록
        public Long save(Lecture lecture) {
            em.persist(lecture);
            return lecture.getId();
        }
    
    
        // 강의 조회
        public Lecture findById(Long id) {
            return em.find(Lecture.class, id);
        }
    
        public List<Lecture> findAll() {
            return em.createQuery("select l from Lecture l", Lecture.class)
                    .getResultList();
        }
    
        public List<Lecture> findByName(String name) {
            return em.createQuery("select l from Lecture l where l.lectureName = :name", Lecture.class)
                    .setParameter("name", name)
                    .getResultList();
        }
    
    
    }
    

     

    테스트코드

    package dongho.classflix.repository;
    
    import dongho.classflix.domain.Lecture;
    import org.assertj.core.api.Assertions;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.persistence.EntityManager;
    
    import java.time.LocalDateTime;
    
    import static org.junit.jupiter.api.Assertions.*;
    
    @SpringBootTest
    @Transactional
    class LectureRepositoryTest {
    
        @Autowired
        LectureRepository lectureRepository;
    
        @Autowired
        EntityManager em;
    
        @Test
        public void 강의저장조회() throws Exception {
            //given
            Lecture lecture = new Lecture("jpa", "김영한", "jpa강의", LocalDateTime.now());
    
            //when
            Long savedId = lectureRepository.save(lecture);
    
            //then
            Assertions.assertThat(lecture).isEqualTo(lectureRepository.findById(savedId));
        }
    }

     

     

    Review

    설계

     

    • 리뷰 저장
    • 리뷰 id로 조회
    • 리뷰 전체 조회
    • 강의에 달린 리뷰 조회

     

    코드

    package dongho.classflix.repository;
    
    import dongho.classflix.domain.Review;
    import lombok.RequiredArgsConstructor;
    import org.springframework.stereotype.Repository;
    
    import javax.persistence.EntityManager;
    import java.util.List;
    
    @Repository
    @RequiredArgsConstructor
    public class ReviewRepository {
        private final EntityManager em;
    
        // 리뷰 저장
        public Long save(Review review) {
            em.persist(review);
            return review.getId();
        }
    
        // 리뷰조회
        public Review findById(Long id) {
            return em.find(Review.class, id);
        }
    
        public List<Review> findAll() {
            return em.createQuery("select r from Review r", Review.class)
                    .getResultList();
        }
    
        // 강의에 달린 리뷰
        public List<Review> findAllWithMemberLecture() {
            return em.createQuery(
                    "select r from Review r" +
                            " join fetch r.lecture l", Review.class
            ).getResultList();
        }
    }
    

     

    테스트코드

    package dongho.classflix.repository;
    
    import dongho.classflix.domain.*;
    import org.assertj.core.api.Assertions;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.annotation.Rollback;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.persistence.EntityManager;
    import javax.swing.*;
    
    import java.time.LocalDateTime;
    
    import static org.junit.jupiter.api.Assertions.*;
    
    @SpringBootTest
    @Transactional
    class ReviewRepositoryTest {
    
        @Autowired
        EntityManager em;
    
        @Autowired
        ReviewRepository reviewRepository;
    
        @Autowired
        MemberRepository memberRepository;
    
        @Autowired
        LectureRepository lectureRepository;
    
    
        @Test
        public void 리뷰저장조회() throws Exception {
            //given
            Member member = new Member("dongho", 25, Gender.MALE);
            em.persist(member);
    
            Lecture lecture = new Lecture("jpa", "김영한", "jpa강의", LocalDateTime.now());
            em.persist(lecture);
    
            Review review = new Review(member, "1234", "good", 4, lecture, LocalDateTime.now());
            //when
    
            Long savedId = reviewRepository.save(review);
    
            //then
            Assertions.assertThat(review).isEqualTo(reviewRepository.findById(savedId));
        }
    }

     

     

     

    서비스

     

    Member

    설계

    • 회원가입(중복회원은 거부)
    • 회원조회

    코드

    package dongho.classflix.service;
    
    import dongho.classflix.domain.Member;
    import dongho.classflix.repository.MemberRepository;
    import lombok.RequiredArgsConstructor;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.util.List;
    
    @Service
    @Transactional
    @RequiredArgsConstructor
    public class MemberService {
    
        private final MemberRepository memberRepository;
    
        /**
         * 회원가입
         */
        public Long join(Member member) {
            validateDuplicateMember(member);
            memberRepository.save(member);
            return member.getId();
        }
    
        // 회원 전체 조회
        @Transactional(readOnly = true)
        public List<Member> findMembers() {
            return memberRepository.findAll();
        }
    
        // 회원 하나 조회
        @Transactional(readOnly = true)
        public Member findOne(Long memberId) {
            return memberRepository.findById(memberId);
        }
    
    
        private void validateDuplicateMember(Member member) {
            List<Member> findMembers = memberRepository.findByName(member.getUserName());
            if (!findMembers.isEmpty()) {
                throw new IllegalArgumentException("이미 존재하는 회원입니다.");
            }
        }
    }
    

     

    테스트코드

    package dongho.classflix.service;
    
    import dongho.classflix.domain.Gender;
    import dongho.classflix.domain.Member;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.persistence.EntityManager;
    
    import static org.junit.jupiter.api.Assertions.*;
    
    @SpringBootTest
    @Transactional
    class MemberServiceTest {
    
        @Autowired
        EntityManager em;
    
        @Autowired
        MemberService memberService;
    
        @Test
        public void 중복회원예외() throws Exception {
            //given
            Member member1 = new Member("dongho", 25, Gender.MALE);
            Member member2 = new Member("dongho", 28, Gender.MALE);
    
            //when
            memberService.join(member1);
    
            //then
            assertThrows(IllegalStateException.class, () -> {
                memberService.join(member2);
            });
        }
    }

     

     

     

    Lecture

    설계

    • 강의등록(중복강의거부 : 강의이름, 강의자이름 두개로)
    • 강의업데이트

     

    코드

    package dongho.classflix.service;
    
    import dongho.classflix.domain.Lecture;
    import dongho.classflix.repository.LectureRepository;
    import lombok.RequiredArgsConstructor;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.net.URI;
    import java.util.List;
    
    @Transactional
    @Service
    @RequiredArgsConstructor
    public class LectureService {
    
        private final LectureRepository lectureRepository;
    
        // 조인
        public Long join(Lecture lecture) {
            validateDuplicateLecture(lecture);
            return lectureRepository.save(lecture);
        }
    
        private void validateDuplicateLecture(Lecture lecture) {
            List<Lecture> findLectures = lectureRepository.findByName(lecture.getLectureName(), lecture.getTeacherName());
            if (!findLectures.isEmpty()) {
                throw new IllegalStateException("이미 존재하는 강의입니다.");
            }
        }
    
        // 업데이트
        public void update(Long id, LectureDto lectureDto) {
            Lecture findLecture = lectureRepository.findById(id);
            findLecture.changeLectureData(lectureDto.getLectureName(), lectureDto.getTeacherName(), lectureDto.getContent(), lectureDto.getRepresentImage(), lectureDto.getSiteName(), lectureDto.getUri());
        }
    }
    

     

    테스트코드

    package dongho.classflix.service;
    
    import dongho.classflix.domain.Lecture;
    import dongho.classflix.repository.LectureRepository;
    import org.assertj.core.api.Assertions;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.persistence.EntityManager;
    
    import java.time.LocalDateTime;
    
    import static org.junit.jupiter.api.Assertions.*;
    
    @SpringBootTest
    @Transactional
    class LectureServiceTest {
        @Autowired
        EntityManager em;
    
        @Autowired
        LectureService lectureService;
    
        @Autowired
        LectureRepository lectureRepository;
    
    
        @Test
        public void 중복강의거부() throws Exception {
            //given
            Lecture lecture1 = new Lecture("jpa", "김영한", "jpa강의", LocalDateTime.now());
            Lecture lecture2 = new Lecture("jpa", "김영한", "jpa강의입니다.", LocalDateTime.now());
    
            //when
            lectureService.join(lecture1);
    
            //then
            assertThrows(IllegalStateException.class, () -> {
                lectureService.join(lecture2);
            });
    
        }
        // 강의 업데이트
        @Test
        public void 강의수정() throws Exception {
            //given
            Lecture lecture = new Lecture("jpa", "김영한", "jpa강의", LocalDateTime.now());
            em.persist(lecture);
    
            LectureDto lectureDto = new LectureDto();
            lectureDto.setContent("data jpa 강의");
    
            //when
            lectureService.update(lecture.getId(), lectureDto);
    
            //then
            Assertions.assertThat(lecture.getContent()).isEqualTo("data jpa 강의");
        }
    }

     

     

     

     

    Review

    설계

    • 리뷰 하나(id) 조회
    • 리뷰 전체 조회
    • 리뷰 수정 (비밀번호 매칭)

    코드

    package dongho.classflix.service;
    
    import dongho.classflix.domain.Lecture;
    import dongho.classflix.domain.Member;
    import dongho.classflix.domain.Review;
    import dongho.classflix.repository.LectureRepository;
    import dongho.classflix.repository.MemberRepository;
    import dongho.classflix.repository.ReviewRepository;
    import lombok.RequiredArgsConstructor;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.util.List;
    
    @Service
    @Transactional
    @RequiredArgsConstructor
    public class ReviewService {
    
        private final ReviewRepository reviewRepository;
        private final MemberRepository memberRepository;
        private final LectureRepository lectureRepository;
    
        // 리뷰 등록
        public Long create(Long memberId, Long lectureId, ReviewDto reviewDto) {
            Member findMember = memberRepository.findById(memberId);
            Lecture findLecture = lectureRepository.findById(lectureId);
    
            Review newReview = new Review(findMember, reviewDto.getPassword(), reviewDto.getContent(), reviewDto.getRating(), findLecture, reviewDto.getReviewDate());
            reviewRepository.save(newReview);
            return newReview.getId();
        }
    
        // 하나 조회
        @Transactional(readOnly = true)
        public Review findOne(Long reviewId) {
            return reviewRepository.findById(reviewId);
        }
    
    
        // 전체 조회
        @Transactional(readOnly = true)
        public List<Review> findAll() {
            return reviewRepository.findAll();
        }
    
        // 리뷰 수정
        public Long update(Long reviewId, String password, String content, Integer rating) {
            Review findReview = reviewRepository.findById(reviewId);
    
            if (!findReview.getPassword().equals(password)) {
                throw new NotEqualPasswordException("password is wrong");
            }
            findReview.changeContentAndRating(content, rating);
            return reviewId;
        }
    
    }
    

     

    테스트코드

    package dongho.classflix.service;
    
    import dongho.classflix.domain.Lecture;
    import dongho.classflix.repository.LectureRepository;
    import org.assertj.core.api.Assertions;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.persistence.EntityManager;
    
    import java.time.LocalDateTime;
    
    import static org.junit.jupiter.api.Assertions.*;
    
    @SpringBootTest
    @Transactional
    class LectureServiceTest {
        @Autowired
        EntityManager em;
    
        @Autowired
        LectureService lectureService;
    
        @Autowired
        LectureRepository lectureRepository;
    
    
        @Test
        public void 중복강의거부() throws Exception {
            //given
            Lecture lecture1 = new Lecture("jpa", "김영한", "jpa강의", LocalDateTime.now());
            Lecture lecture2 = new Lecture("jpa", "김영한", "jpa강의입니다.", LocalDateTime.now());
    
            //when
            lectureService.join(lecture1);
    
            //then
            assertThrows(IllegalStateException.class, () -> {
                lectureService.join(lecture2);
            });
    
        }
        // 강의 업데이트
        @Test
        public void 강의수정() throws Exception {
            //given
            Lecture lecture = new Lecture("jpa", "김영한", "jpa강의", LocalDateTime.now());
            em.persist(lecture);
    
            LectureDto lectureDto = new LectureDto();
            lectureDto.setContent("data jpa 강의");
    
            //when
            lectureService.update(lecture.getId(), lectureDto);
    
            //then
            Assertions.assertThat(lecture.getContent()).isEqualTo("data jpa 강의");
        }
    }

     

     

     

     

     

    테스트 코드 실행 결과