[Spring Security] 온라인 시험 사이트 구현(2. 도메인 설계:시험지 탬플릿 도메인)

WOOK JONG KIM·2022년 12월 7일
0

패캠_java&Spring

목록 보기
91/103
post-thumbnail

템플릿 시험지 / 문제

  • 시험지를 한개 만든다.
  • 문제를 추가한다.
  • 문제를 삭제한다.

시험지

  • 조건) 선생님, 학생1, 학생2
  • 조건) 2문제로 된 시험지 템플릿이 있다.
  • 시험지 템플릿을 학생1 에게 시험지를 낸다.
  • 시험지를 2명 이상의 학생에게 낸다. (학생1, 학생2)
  • 시험지를 삭제한다.

문제 풀기

  • 조건) 선생님, 학생1, 학생2
  • 조건) 2문제로 된 시험지가 있다.
  • 시험지를 모두 풀어서 100점을 맞는다
  • 문제를 한개 틀려서 50점을 맞는다.
  • 문제를 모두 틀려서 0점을 맞는다.
  • 1번 문제 풀고 중간에 제출해 버린다
  • 2문제 풀고 중간에 제출해 버린다.
  • 문제를 풀지 않고 그냥 제출해 버린다
  • 상태에 따라 시험지가 조회된다

시험지 템플릿 도메인

Paper.java

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
@Table(name = "sp_paper")
public class Paper {

    // 학생들에게 배부될 시험지

    @Id
    @GeneratedValue
    private Long PaperId;

    private Long paperTemplateId; // 이를 기반으로 만들어 짐
    private String name;

    private Long studyUserId; // 학생 아이디

    @Transient
    private User user;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "paper")
    private List<PaperAnswer> paperAnswerList;


    private LocalDateTime created;
    private LocalDateTime startTime;
    private LocalDateTime endTime;

    private PaperState state;

    public static enum PaperState {
        READY,
        START,
        END,
        CANCELED
    }

    private int total;
    private int answered;
    private int correct;

    @Transient
    public double getScore(){
        if(total < 1) return 0;
        return correct* 100.0 / total;
    }

    public void addAnswered() {
        answered++;
    }

    public void addCorrect() {
        correct++;
    }

    public Map<Integer, PaperAnswer> answerMap(){
        if(paperAnswerList == null) return new HashMap<>();
        return paperAnswerList.stream().collect(Collectors.toMap(PaperAnswer::num,
                Function.identity()));
    }

}

PaperAnswer

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
@Table
public class PaperAnswer {

    @JsonIgnore
    @ManyToOne
    @JoinColumn(foreignKey = @ForeignKey(name = "paperId"))
    Paper paper;

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Embeddable
    public static class PaperAnswerId implements Serializable {
        private Long paperId;
        private Integer num; // 1-base(1,2,3,4~~~) // 이 두 필드가 Unique한 Id 역할을 하게 끔
    }

    @EmbeddedId
    private PaperAnswerId id;

    private Long problemId;
    private String answer;
    private boolean correct;

    private LocalDateTime answered;

    public Integer num(){
        return id.getNum();
    }

}

PaperTemplate.java

Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
@Table(name="sp_paper_template")
public class PaperTemplate {

    // 선생님이 작성하는 시험지

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long paperTemplateId;

    private String name;

    private Long userId;

    @Transient
    private User creator; // 작성자 아이디

    private int total; // problemList 갯수를 사용하기 위해 매번 접근하는 것은 부담

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(foreignKey = @ForeignKey(name="paperTemplateId"))
    private List<Problem> problemList;

    private long publishedCount;

    private long completeCount;

    @Column(updatable = false)
    private LocalDateTime created;

    private LocalDateTime updated;
}

Problem.java

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
@Table(name = "sp_problem")
public class Problem {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long problemId;

    private Long paperTemplateId;

    private int indexNum; // 1번 부터 2,3,4~~~

    private String content;

    private String answer; // paper answer와 correct 한지 확인 하기 위해

    @Column(updatable = false)
    private LocalDateTime created;

    private LocalDateTime updated;
}

PaperAnswerRepository

public interface PaperAnswerRepository extends JpaRepository<PaperAnswer, PaperAnswer.PaperAnswerId> {

}

PaperRepository

public interface PaperRepository extends JpaRepository<Paper, Long> {

    List<Paper> findAllByPaperTemplateIdAndStudyUserIdIn(Long paperTemplateId, List<Long> studyIdlist);

    List<Paper> findAllByPaperTemplateId(Long paperTemplateId);
    long countByPaperTemplateId(Long paperTemplateId);

    List<Paper> findAllByStudyUserIdOrderByCreatedDesc(Long studyUserId);
    long countByStudyUserId(Long studyUserId);

    Page<Paper> findAllByStudyUserIdAndStateOrderByCreatedDesc(Long studyUserId, Paper.PaperState state, Pageable pageable);

    List<Paper> findAllByStudyUserIdAndStateOrderByCreatedDesc(Long studyUserId, Paper.PaperState state);
    long countByStudyUserIdAndState(Long studyUserId, Paper.PaperState state);

    List<Paper> findAllByStudyUserIdAndStateInOrderByCreatedDesc(Long studyUserId, List<Paper.PaperState> states);
    long countByStudyUserIdAndStateIn(Long studyUserId, List<Paper.PaperState> states);
}

PaperTemplateRepository

public interface PaperTemplateRepository extends JpaRepository<PaperTemplate, Long> {

    List<PaperTemplate> findAllByUserIdOrderByCreatedDesc(Long userId);

    Page<PaperTemplate> findAllByUserIdOrderByCreatedDesc(Long userId, Pageable pageable);

    long countByUserId(Long userId);

}

ProblemRepository

public interface ProblemRepository extends JpaRepository<Problem, Long> {

    List<Problem> findAllByPaperTemplateIdOrderByIndexNumAsc(Long paperTemplateId);

    @Modifying
    @Query("update Problem set content=?2, answer=?3, updated=?4 where problemId=?1")
    void updateProblem(long problemId, String content, String answer, LocalDateTime now);

}

PaperService.java

@Service
@RequiredArgsConstructor
@Transactional
public class PaperService {

    private final UserRepository userRepository;
    private final PaperTemplateService paperTemplateService;
    private final PaperRepository paperRepository;
    private final PaperAnswerRepository paperAnswerRepository;

    protected Paper save(Paper paper){
        if(paper.getPaperId() == null){
            paper.setCreated(LocalDateTime.now());
        }
        return paperRepository.save(paper);
    }

    @Transactional
    // 시험지를 나눠줄때 해당 메서드 실행(study -> student라 생각하자)
    public List<Paper> publishPaper(long paperTemplateId, List<Long> studyIdList){
        List<Paper> papers = paperTemplateService.findById(paperTemplateId).map(paperTemplate ->
                StreamSupport.stream(userRepository.findAllById(studyIdList).spliterator(), false)
                        .map(study -> {
                            Paper paper = Paper.builder()
                                    .paperTemplateId(paperTemplate.getPaperTemplateId())
                                    .name(paperTemplate.getName())
                                    .state(Paper.PaperState.READY)
                                    .studyUserId(study.getUserId())
                                    .total(paperTemplate.getTotal())
                                    .build();
                            return save(paper);
                        }).collect(Collectors.toList())
        ).orElseThrow(()->new IllegalArgumentException(paperTemplateId+" 시험지 템플릿이 존재하지 않습니다."));
        paperTemplateService.updatePublishedCount(paperTemplateId, papers.size());
        return papers;
    }

    public void removePaper(long paperTemplateId, List<Long> studyIdList){
        paperRepository.findAllByPaperTemplateIdAndStudyUserIdIn(paperTemplateId, studyIdList)
                .forEach(paper -> {
                    paperRepository.delete(paper);
                });
    }

    @Transactional
    // 문제를 풀때마다 , paperId로 페이퍼를 찾고 해당 페이퍼에 Answer이 있다면 마킹한 내용 업데이트
    public void answer(Long paperId, Long problemId, int num, String answer){
        paperRepository.findById(paperId).ifPresentOrElse(paper->{
            Optional<PaperAnswer> pa = paper.getPaperAnswerList() == null ? Optional.empty() :
                    paper.getPaperAnswerList().stream().filter(a -> a.getId().getNum() == num).findFirst();
            if(pa.isPresent()){
                PaperAnswer pAnswer = pa.get();
                pAnswer.setAnswer(answer);
                pAnswer.setAnswered(LocalDateTime.now());
                pAnswer.setProblemId(problemId);
                paperAnswerRepository.save(pAnswer);
            }else{
                PaperAnswer pAnswer = PaperAnswer.builder()
                        .id(new PaperAnswer.PaperAnswerId(paperId, num))
                        .problemId(problemId)
                        .answer(answer)
                        .answered(LocalDateTime.now())
                        .build();
//                paperAnswerRepository.save(pAnswer);
                pAnswer.setPaper(paper);
                if(paper.getPaperAnswerList() == null) paper.setPaperAnswerList(new ArrayList<>());
                paper.getPaperAnswerList().add(pAnswer);
                paper.addAnswered();
                if(paper.getState() != Paper.PaperState.START){
                    paper.setState(Paper.PaperState.START);
                    paper.setStartTime(LocalDateTime.now());
                }
                paperRepository.save(paper);
            }
        }, ()->new IllegalArgumentException(paperId+" 시험지를 찾을 수 없습니다."));
    }

    @Transactional
    public void paperDone(Long paperId){
        // 시험을 끝냈으면 해당 시험지의 답안을 비교해서 채점 한다.
        final Paper paper = paperRepository.findById(paperId).orElseThrow(()->new IllegalArgumentException(paperId+" 시험지를 찾을 수 없습니다."));
        final Map<Integer, String> answerSheet = paperTemplateService.getPaperAnswerSheet(paper.getPaperTemplateId());
        paper.setCorrect(0);
        if(paper.getPaperAnswerList() != null) {
            paper.getPaperAnswerList().forEach(answer -> {
                if (answer.getAnswer() != null && answer.getAnswer().equals(answerSheet.get(answer.getId().getNum()))) {
                    answer.setCorrect(true); // 정답인지 아닌지 마킹
                    paper.addCorrect(); // score는 자동으로 계산됨
                    paperAnswerRepository.save(answer);
                }
            });
        }
        paper.setState(Paper.PaperState.END);
        paper.setEndTime(LocalDateTime.now());
        Paper saved = paperRepository.save(paper);
//        paperTemplateService.findById(saved.getPaperTemplateId()).map(paperTemplate -> paperTemplate.setCompleteCount(saved.))
        paperTemplateService.updateCompleteCount(saved.getPaperTemplateId());
    }

    @Transactional(readOnly = true)
    public List<Paper> getPapers(Long paperTemplateId) {
        return paperRepository.findAllByPaperTemplateId(paperTemplateId);
    }

    @Transactional(readOnly = true)
    public List<Paper> getPapersByUser(Long studyUserId) {
        return paperRepository.findAllByStudyUserIdOrderByCreatedDesc(studyUserId);
    }

    @Transactional(readOnly = true)
    public List<Paper> getPapersByUserState(Long studyUserId, Paper.PaperState state) {
        return paperRepository.findAllByStudyUserIdAndStateOrderByCreatedDesc(studyUserId, state);
    }

    @Transactional(readOnly = true)
    public List<Paper> getPapersByUserIng(Long studyUserId) {
        return paperRepository.findAllByStudyUserIdAndStateInOrderByCreatedDesc(studyUserId, List.of(Paper.PaperState.READY, Paper.PaperState.START));
    }

    @Transactional(readOnly = true)
    public long countPapersByUserIng(Long studyUserId) {
        return paperRepository.countByStudyUserIdAndStateIn(studyUserId, List.of(Paper.PaperState.READY, Paper.PaperState.START));
    }

    @Transactional(readOnly = true)
    public Page<Paper> getPapersByUserResult(Long studyUserId, int pageNum, int size) {
        return paperRepository.findAllByStudyUserIdAndStateOrderByCreatedDesc(studyUserId, Paper.PaperState.END, PageRequest.of(pageNum-1, size));
    }

    @Transactional(readOnly = true)
    public long countPapersByUserResult(Long studyUserId) {
        return paperRepository.countByStudyUserIdAndState(studyUserId, Paper.PaperState.END);
    }

    @Transactional(readOnly = true)
    public List<Paper> getPapersByUserState(Long studyUserId, List<Paper.PaperState> states) {
        return paperRepository.findAllByStudyUserIdAndStateInOrderByCreatedDesc(studyUserId, states);
    }

    @Transactional(readOnly = true)
    public Optional<Paper> findPaper(Long paperId) {
        return paperRepository.findById(paperId);
    }

}

PaperTemplateService

@Transactional
@Service
@RequiredArgsConstructor
public class PaperTemplateService {

    private final PaperTemplateRepository paperTemplateRepository;
    private final ProblemService problemService;

    public PaperTemplate save(PaperTemplate paperTemplate) {
        if(paperTemplate.getPaperTemplateId() == null){
            paperTemplate.setCreated(LocalDateTime.now());
        }
        paperTemplate.setUpdated(LocalDateTime.now());
        return paperTemplateRepository.save(paperTemplate);
    }

    // 문제 한개씩 추가
    public Problem addProblem(long paperTemplateId, Problem problem){
        problem.setPaperTemplateId(paperTemplateId);
        return findById(paperTemplateId).map(paperTemplate -> {
            if(paperTemplate.getProblemList() == null){
                paperTemplate.setProblemList(new ArrayList<>());
            }
            problem.setCreated(LocalDateTime.now());
            paperTemplate.getProblemList().add(problem);
            IntStream.rangeClosed(1, paperTemplate.getProblemList().size()).forEach(i->{
                paperTemplate.getProblemList().get(i-1).setIndexNum(i);
            });
            paperTemplate.setTotal(paperTemplate.getProblemList().size());
            Problem saved = problemService.save(problem);
            save(paperTemplate);
            return saved;
        }).orElseThrow(()-> new IllegalArgumentException(paperTemplateId+" 아이디 시험지가 없습니다."));
    }

    public Optional<PaperTemplate> findById(long paperTemplateId) {
        return paperTemplateRepository.findById(paperTemplateId);
    }

    public PaperTemplate removeProblem(long paperTemplateId, long problemId){
        return findById(paperTemplateId).map(paperTemplate -> {
            if(paperTemplate.getProblemList() == null){
                return paperTemplate;
            }
            Optional<Problem> problem = paperTemplate.getProblemList().stream().filter(p -> p.getProblemId().equals(problemId)).findFirst();
            if(problem.isPresent()){
                paperTemplate.setProblemList(
                        paperTemplate.getProblemList().stream().filter(p -> !p.getProblemId().equals(problemId))
                                .collect(Collectors.toList())
                );
                problemService.delete(problem.get());
                IntStream.rangeClosed(1, paperTemplate.getProblemList().size()).forEach(i->{
                    paperTemplate.getProblemList().get(i-1).setIndexNum(i);
                });
            }
            paperTemplate.setTotal(paperTemplate.getProblemList().size());
            return save(paperTemplate);
        }).orElseThrow(()-> new IllegalArgumentException(paperTemplateId+" 아이디 시험지가 없습니다."));
    }


    public void update(long problemId, String content, String answer){
        problemService.updateProblem(problemId, content, answer);
    }

    @Transactional(readOnly = true)
    public Optional<PaperTemplate> findProblemTemplate(Long paperTemplateId) {
        return paperTemplateRepository.findById(paperTemplateId).map(pt->{
            if(pt.getProblemList().size() != pt.getTotal()){ // lazy 해결위해 체크..., 혹시나 total과 list 사이즈가 다를까봐
                pt.setTotal(pt.getProblemList().size());
            }
            return pt;
        });
    }

    @Transactional(readOnly = true)
    public Map<Integer, String> getPaperAnswerSheet(Long paperTemplateId) {
        Optional<PaperTemplate> template = findById(paperTemplateId);
        if(!template.isPresent()) return new HashMap<>();
        // Map으로 가져오면 정답을 가져올때 유용
        return template.get().getProblemList().stream().collect(Collectors.toMap(Problem::getIndexNum, Problem::getAnswer));
    }

    @Transactional(readOnly = true)
    public List<PaperTemplate> findByTeacherId(Long userId) {
        return paperTemplateRepository.findAllByUserIdOrderByCreatedDesc(userId);
    }

    @Transactional(readOnly = true)
    public Page<PaperTemplate> findByTeacherId(Long userId, int pageNum, int size) {
        return paperTemplateRepository.findAllByUserIdOrderByCreatedDesc(userId, PageRequest.of(pageNum-1, size));
    }

    @Transactional(readOnly = true)
    public Object countByUserId(Long userId) {
        return paperTemplateRepository.countByUserId(userId);
    }

    // Controller가 학생에게 시험지를 배부할때
    public void updatePublishedCount(long paperTemplateId, long publishedCount) {
        paperTemplateRepository.findById(paperTemplateId).ifPresent(paperTemplate -> {
            paperTemplate.setPublishedCount(publishedCount);
            paperTemplateRepository.save(paperTemplate);
        });
    }

    public void updateCompleteCount(Long paperTemplateId) {
        paperTemplateRepository.findById(paperTemplateId).ifPresent(paperTemplate -> {
            paperTemplate.setCompleteCount(paperTemplate.getCompleteCount()+1);
            paperTemplateRepository.save(paperTemplate);
        });
    }
}

ProblemService

@Service
@Transactional
@RequiredArgsConstructor
public class ProblemService {

    private final ProblemRepository problemRepository;

    public Problem save(Problem problem) {
        if(problem.getProblemId() == null){
            problem.setCreated(LocalDateTime.now());
        }
        problem.setUpdated(LocalDateTime.now());
        return problemRepository.save(problem);
    }

    public Optional<Problem> findProblem(Long problemId){
        return problemRepository.findById(problemId);
    }

    public List<Problem> listProblems(long paperTemplateId){
        return problemRepository.findAllByPaperTemplateIdOrderByIndexNumAsc(paperTemplateId);
    }

    public void delete(Problem problem) {
        problemRepository.delete(problem);
    }

    public void updateProblem(long problemId, String content, String answer) {
        problemRepository.updateProblem(problemId, content, answer, LocalDateTime.now());
    }

}

테스트코드

@RequiredArgsConstructor
public class PaperTemplateTestHelper {

    private final PaperTemplateService paperTemplateService;

    public PaperTemplate createPaperTemplate(User teacher, String paperName){
        PaperTemplate paperTemplate = PaperTemplate.builder()
                .name(paperName)
                .creator(teacher)
                .build();
        return paperTemplateService.save(paperTemplate);
    }

    public Problem addProblem(long paperTemplateId, Problem problem){
        return paperTemplateService.addProblem(paperTemplateId, problem);
    }

    public static void assertPaperTemplate(PaperTemplate pt, User user, String paperName) {
        assertNotNull(pt.getPaperTemplateId());
        assertNotNull(pt.getCreated());
        assertNotNull(pt.getUpdated());
        assertEquals(paperName, pt.getName());
        assertEquals(user.getUserId(), pt.getCreator().getUserId());
    }

}
public class WithPaperTemplateTest extends WithUserTest {

    @Autowired
    protected PaperTemplateRepository paperTemplateRepository;
    @Autowired
    protected ProblemRepository problemRepository;

    protected PaperTemplateService paperTemplateService;
    protected PaperTemplateTestHelper paperTemplateTestHelper;
    protected ProblemService problemService;
    protected User teacher;

    protected void preparePaperTemplate(){
        this.problemRepository.deleteAll();
        this.paperTemplateRepository.deleteAll();

        prepareUserServices();

        this.problemService = new ProblemService(problemRepository);
        this.paperTemplateService = new PaperTemplateService(paperTemplateRepository, problemService);
        this.paperTemplateTestHelper = new PaperTemplateTestHelper(this.paperTemplateService);

        this.teacher = this.userTestHelper.createTeacher(school, "선생님1");
    }

    protected Problem problem(long ptId, String content, String answer){
        return Problem.builder().paperTemplateId(ptId)
                .content(content).answer(answer).build();
    }

}
@DisplayName("학습자가 시험지를 푸는 것에 대해서 테스트 한다. ")
@DataJpaTest
public class PaperSolveTest extends WithPaperTemplateTest {

    @Autowired
    private PaperRepository paperRepository;
    @Autowired
    private PaperAnswerRepository paperAnswerRepository;

    private PaperService paperService;

    private PaperTemplate paperTemplate;
    private Problem problem1;
    private Problem problem2;

    private User study1;
    private Paper paper;

    @BeforeEach
    void before(){
        paperRepository.deleteAll();
        preparePaperTemplate();

        this.paperService = new PaperService(userRepository, paperTemplateService, paperRepository, paperAnswerRepository);
        this.study1 = this.userTestHelper.createStudent(school, teacher, "study1", "중1");
        this.paperTemplate = this.paperTemplateTestHelper.createPaperTemplate(teacher, "시험지1");
        this.problem1 = this.paperTemplateTestHelper.addProblem(paperTemplate.getPaperTemplateId(),
                problem(paperTemplate.getPaperTemplateId(), "문제1", "답1"));
        this.problem2 = this.paperTemplateTestHelper.addProblem(paperTemplate.getPaperTemplateId(),
                problem(paperTemplate.getPaperTemplateId(), "문제2", "답2"));
        this.paper = paperService.publishPaper(paperTemplate.getPaperTemplateId(), List.of(study1.getUserId())).get(0);
    }

    @DisplayName("1. 시험지를 모두 풀어서 100점을 맞는다.")
    @Test
    void 시험지를_모두_풀어서_100점을_맞는다() {

        paperService.answer(paper.getPaperId(), problem1.getProblemId(), 1, "답1");
        Paper ingPaper = paperService.findPaper(this.paper.getPaperId()).get();
        assertEquals(2, ingPaper.getTotal());
        assertEquals(1, ingPaper.getAnswered());
        assertEquals(0, ingPaper.getCorrect());
        assertEquals(Paper.PaperState.START, ingPaper.getState());
        assertNotNull(ingPaper.getStartTime());
        assertNull(ingPaper.getEndTime());

        paperService.answer(paper.getPaperId(), problem2.getProblemId(), 2, "답2");
        ingPaper = paperService.findPaper(this.paper.getPaperId()).get();
        assertEquals(2, ingPaper.getTotal());
        assertEquals(2, ingPaper.getAnswered());
        assertEquals(0, ingPaper.getCorrect());
        assertEquals(Paper.PaperState.START, ingPaper.getState());
        assertNotNull(ingPaper.getStartTime());
        assertNull(ingPaper.getEndTime());

        paperService.paperDone(paper.getPaperId());

        Paper resultPaper = paperService.findPaper(this.paper.getPaperId()).get();
        assertEquals(2, resultPaper.getTotal());
        assertEquals(2, resultPaper.getAnswered());
        assertEquals(2, resultPaper.getCorrect());
        assertEquals(Paper.PaperState.END, resultPaper.getState());
        assertNotNull(resultPaper.getStartTime());
        assertNotNull(resultPaper.getEndTime());

        PaperTemplate result = paperTemplateService.findById(paperTemplate.getPaperTemplateId()).get();
        assertEquals(1, result.getPublishedCount());
        assertEquals(1, result.getCompleteCount());
    }

    @DisplayName("2. 문제를 한개 틀려서 50점을 맞는다.")
    @Test
    void 문제를_한개_틀려서_50점을_맞는다() {
        paperService.answer(paper.getPaperId(), problem1.getProblemId(), 1, "답1");
        paperService.answer(paper.getPaperId(), problem2.getProblemId(), 2, "오답");
        paperService.paperDone(paper.getPaperId());
        Paper resultPaper = paperService.findPaper(this.paper.getPaperId()).get();
        assertEquals(2, resultPaper.getTotal());
        assertEquals(2, resultPaper.getAnswered());
        assertEquals(1, resultPaper.getCorrect());
    }

    @DisplayName("3. 문제를 모두 틀려서 0점을 맞는다.")
    @Test
    void 문제를_모두_틀려서_0점을_맞는다() {
        paperService.answer(paper.getPaperId(), problem1.getProblemId(), 1, "오답");
        paperService.answer(paper.getPaperId(), problem2.getProblemId(), 2, "오답");
        paperService.paperDone(paper.getPaperId());
        Paper resultPaper = paperService.findPaper(this.paper.getPaperId()).get();
        assertEquals(2, resultPaper.getTotal());
        assertEquals(2, resultPaper.getAnswered());
        assertEquals(0, resultPaper.getCorrect());
    }

    @DisplayName("4. 1번 문제 풀고 중간에 제출해 버린다.")
    @Test
    void 첫번째_문제_풀고_중간에_제출해_버린다() {
        paperService.answer(paper.getPaperId(), problem1.getProblemId(), 1, "답1");
        paperService.paperDone(paper.getPaperId());
        Paper resultPaper = paperService.findPaper(this.paper.getPaperId()).get();
        assertEquals(2, resultPaper.getTotal());
        assertEquals(1, resultPaper.getAnswered());
        assertEquals(1, resultPaper.getCorrect());
    }

    @DisplayName("5. 2문제 풀고 중간에 제출해 버린다.")
    @Test
    void 두번째_문제_풀고_중간에_제출해_버린다() {
        paperService.answer(paper.getPaperId(), problem2.getProblemId(), 2, "답2");
        paperService.paperDone(paper.getPaperId());
        Paper resultPaper = paperService.findPaper(this.paper.getPaperId()).get();
        assertEquals(2, resultPaper.getTotal());
        assertEquals(1, resultPaper.getAnswered());
        assertEquals(1, resultPaper.getCorrect());
    }

    @DisplayName("6. 문제를 풀지 않고 그냥 제출해 버린다.")
    @Test
    void 문제를_풀지_않고_그냥_제출해_버린다() {
        paperService.paperDone(paper.getPaperId());
        Paper resultPaper = paperService.findPaper(this.paper.getPaperId()).get();
        assertEquals(2, resultPaper.getTotal());
        assertEquals(0, resultPaper.getAnswered());
        assertEquals(0, resultPaper.getCorrect());
    }

    @DisplayName("7. 상태에 따라 시험지가 조회된다.")
    @Test
    void 상태에_따라_시험지가_조회된다() {
        assertEquals(1, paperService.getPapersByUserState(study1.getUserId(), List.of(Paper.PaperState.READY, Paper.PaperState.START)).size());
        assertEquals(0, paperService.getPapersByUserState(study1.getUserId(), Paper.PaperState.END).size());

        paperService.answer(paper.getPaperId(), problem2.getProblemId(), 2, "답2");
        assertEquals(1, paperService.getPapersByUserState(study1.getUserId(), List.of(Paper.PaperState.READY, Paper.PaperState.START)).size());
        assertEquals(0, paperService.getPapersByUserState(study1.getUserId(), Paper.PaperState.END).size());

        paperService.paperDone(paper.getPaperId());

        assertEquals(0, paperService.getPapersByUserState(study1.getUserId(), List.of(Paper.PaperState.READY, Paper.PaperState.START)).size());
        assertEquals(1, paperService.getPapersByUserState(study1.getUserId(), Paper.PaperState.END).size());
    }

}

PaperTemplateTest

@DataJpaTest
public class PaperTemplateTest extends WithPaperTemplateTest {

    private PaperTemplate template;

    @BeforeEach
    void before(){
        preparePaperTemplate();
        template = paperTemplateTestHelper.createPaperTemplate(teacher, "paper1");
    }

    private Problem problem(String content, String answer){
        return Problem.builder().paperTemplateId(template.getPaperTemplateId())
                .content(content)
                .answer(answer)
                .build();
    }

    @DisplayName("1. 시험지를 한개 만든다.")
    @Test
    void test_1(){
        assertEquals(1, paperTemplateRepository.count());
        PaperTemplateTestHelper.assertPaperTemplate(
                paperTemplateRepository.findAll().get(0), teacher, "paper1");
    }


    @DisplayName("2. 문제를 추가한다.")
    @Test
    void test_2() {
        paperTemplateTestHelper.addProblem(template.getPaperTemplateId(), problem("문제1", "정답1"));
        paperTemplateTestHelper.addProblem(template.getPaperTemplateId(), problem("문제2", "정답2"));
        paperTemplateTestHelper.addProblem(template.getPaperTemplateId(), problem("문제3", "정답3"));

        assertEquals(3, paperTemplateRepository.findAll().get(0).getProblemList().size());
    }

    @DisplayName("3. 문제를 삭제한다.")
    @Test
    void test_3() {
        paperTemplateTestHelper.addProblem(template.getPaperTemplateId(), problem("문제1", "정답1"));
        paperTemplateTestHelper.addProblem(template.getPaperTemplateId(), problem("문제2", "정답2"));
        paperTemplateTestHelper.addProblem(template.getPaperTemplateId(), problem("문제3", "정답3"));
        PaperTemplate paperTemplate = paperTemplateRepository.findAll().get(0);
        paperTemplateService.removeProblem(template.getPaperTemplateId(), paperTemplate.getProblemList().get(1).getProblemId());

        assertEquals(2, paperTemplateRepository.findAll().get(0).getProblemList().size());
        paperTemplate = paperTemplateRepository.findAll().get(0);
        assertEquals(1, paperTemplate.getProblemList().get(0).getIndexNum());
        assertEquals(2, paperTemplate.getProblemList().get(1).getIndexNum());

        assertEquals("문제3", paperTemplate.getProblemList().get(1).getContent());
    }

}
@DisplayName("템플릿을 가지고 학습자들에게 시험지를 낸다.")
@DataJpaTest
public class PaperTest extends WithPaperTemplateTest {

    @Autowired
    private PaperRepository paperRepository;
    @Autowired
    private PaperAnswerRepository paperAnswerRepository;

    private PaperService paperService;

    private PaperTemplate paperTemplate;
    private User study1;
    private User study2;

    @BeforeEach
    void before(){
        paperRepository.deleteAll();

        preparePaperTemplate();

        this.paperService = new PaperService(userRepository, paperTemplateService, paperRepository, paperAnswerRepository);

        this.study1 = this.userTestHelper.createStudent(school, teacher, "study1", "중1");
        this.study2 = this.userTestHelper.createStudent(school, teacher, "study2", "중1");

        this.paperTemplate = this.paperTemplateTestHelper.createPaperTemplate(teacher, "시험지1");
        this.paperTemplateTestHelper.addProblem(paperTemplate.getPaperTemplateId(),
                problem(paperTemplate.getPaperTemplateId(), "문제1", "답1"));
        this.paperTemplateTestHelper.addProblem(paperTemplate.getPaperTemplateId(),
                problem(paperTemplate.getPaperTemplateId(), "문제2", "답2"));
    }


    @DisplayName("1. 시험지 템플릿을 학습자1에게 시험지를 낸다.")
    @Test
    void 시험지_템플릿을_학습자1에게_시험지를_낸다() {
        paperService.publishPaper(paperTemplate.getPaperTemplateId(), List.of(study1.getUserId()));

        List<Paper> papers = paperService.getPapers(paperTemplate.getPaperTemplateId());
        assertEquals(1, papers.size());

        Paper paper = papers.get(0);
        assertNotNull(paper.getPaperId());
        assertNotNull(paper.getCreated());
        assertEquals(study1.getUserId(), paper.getStudyUserId());
        assertEquals(paperTemplate.getPaperTemplateId(), paper.getPaperTemplateId());
        assertEquals(paperTemplate.getName(), paper.getName());
        assertNull(paper.getStartTime());
        assertNull(paper.getEndTime());
        assertEquals(Paper.PaperState.READY, paper.getState());
        assertEquals(2, paper.getTotal());
        assertEquals(0, paper.getAnswered());
        assertEquals(0, paper.getCorrect());

        PaperTemplate result = paperTemplateService.findById(paperTemplate.getPaperTemplateId()).get();
        assertEquals(1, result.getPublishedCount());
        assertEquals(0, result.getCompleteCount());
    }

    @DisplayName("2. 시험지를 2명 이상의 user 를 검색해 낸다. (학습자1, 학습자2) ")
    @Test
    void 시험지를_2명_이상의_user를_검색해_낸다() {
        paperService.publishPaper(paperTemplate.getPaperTemplateId(), List.of(study1.getUserId(), study2.getUserId()));

        List<Paper> papers = paperService.getPapers(paperTemplate.getPaperTemplateId());
        assertEquals(2, papers.size());
    }

    @DisplayName("3. 시험지 삭제 기능")
    @Test
    void 시험지_삭제_기능() {
        paperService.publishPaper(paperTemplate.getPaperTemplateId(), List.of(study1.getUserId(), study2.getUserId()));

        paperService.removePaper(paperTemplate.getPaperTemplateId(), List.of(study1.getUserId()));
        List<Paper> papers = paperService.getPapers(paperTemplate.getPaperTemplateId());
        assertEquals(1, papers.size());

        paperService.removePaper(paperTemplate.getPaperTemplateId(), List.of(study2.getUserId()));
        papers = paperService.getPapers(paperTemplate.getPaperTemplateId());
        assertEquals(0, papers.size());

        paperService.removePaper(paperTemplate.getPaperTemplateId(), List.of(study2.getUserId()));
        papers = paperService.getPapers(paperTemplate.getPaperTemplateId());
        assertEquals(0, papers.size());
    }


}

PaperTestApplication

@SpringBootApplication(scanBasePackages = {
        "com.sp.fc.config"
})
public class PaperTestApp {

    public static void main(String[] args) {
        SpringApplication.run(PaperTestApp.class, args);
    }

    @Configuration
    @EntityScan(basePackages = {
            "com.sp.fc.user.domain",
            "com.sp.fc.paper.domain"
    })
    @EnableJpaRepositories(basePackages = {
            "com.sp.fc.user.repository",
            "com.sp.fc.paper.repository"
    })
    class JpaConfig {

    }
}

build.gradle

dependencies {

    implementation("$boot:spring-boot-starter-data-jpa")

    testRuntime("com.h2database:h2")

    compile project(":comp-paper-user")
    testCompile project(":comp-paper-user").sourceSets.test.output
}
profile
Journey for Backend Developer

0개의 댓글