[Spring] Spring Jdbc 테스트 적용하기

김민범·2024년 11월 6일

Spring

목록 보기
12/29

연습삼아 만들었던 게시판 api 에 테스트 코드를 적용해보기로 했다.

간단하게 posts, comments 두 개의 테이블을 가지고 진행한 작업이고, 각 Service 에 테스트를 했다.

PostServiceTest

package com.example.spring_board.service;

import com.example.spring_board.dto.post.CreatePostReqDto;
import com.example.spring_board.dto.post.PostReqDto;
import com.example.spring_board.dto.post.PostResDto;
import com.example.spring_board.repository.post.PostRepo;
import com.example.spring_board.service.post.PostService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.server.ResponseStatusException;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

@SpringBootTest
@Transactional
public class PostServiceTest {

    @Autowired
    PostService postService;
    @Autowired
    PostRepo postRepo;

    @Test
    public void 게시글생성조회() {
        CreatePostReqDto post = new CreatePostReqDto("0000", "test", "testContents");

        Long saveId = postService.createPost(post).getId();

        PostResDto findPost = postService.findPostById(saveId);
        assertThat(post.getContents()).isEqualTo(findPost.getContents());
    }

    @Test
    public void 게시글전체조회() {
        for (int i = 0; i < 100; i++) {
            CreatePostReqDto post = new CreatePostReqDto("0000", "test" + i, "testCon" + i);
            postService.createPost(post);
        }

        Page<PostResDto> pagePosts = postService.findAllPosts(0, 10);

        assertThat(pagePosts.getTotalElements()).isEqualTo(100L);
        assertThat(pagePosts.getTotalPages()).isEqualTo(10);

        //  게시글 항목 조회 type
        List<PostResDto> postList = pagePosts.getContent();
        PostResDto firstPost = postList.get(0); // 첫 번째 게시글 가져오기

        assertThat(firstPost.getTitle()).isEqualTo("test99"); // 첫 번째 글의 제목 검증
        assertThat(firstPost.getContents()).isEqualTo("testCon99"); // 첫 번째 글의 내용 검증
    }

    @Test
    public void 게시글수정() {
        CreatePostReqDto post = new CreatePostReqDto("0000", "test", "testContents");
        PostResDto created = postService.createPost(post);

        PostReqDto updatePostReq = new PostReqDto("patchTest", "0000", "patchTestContents");
        PostResDto updatedPost = postService.updatePost(created.getId(), updatePostReq);

        assertThat(updatedPost.getTitle()).isEqualTo("patchTest");
        assertThat(updatedPost.getContents()).isEqualTo("patchTestContents");
    }

    @Test
    public void patchAndDeleteException_invalidPassword() {
        CreatePostReqDto post = new CreatePostReqDto("0000", "test", "testContents");
        PostResDto created = postService.createPost(post);

        PostReqDto updatePostReq = new PostReqDto("patchTest", "1000", "patchTestContents");
        PostReqDto deletePostReq = new PostReqDto(null, "1000", null);

        ResponseStatusException updateErr = assertThrows(ResponseStatusException.class, () -> postService.updatePost(created.getId(), updatePostReq));
        ResponseStatusException deleteErr = assertThrows(ResponseStatusException.class, () -> postService.deletePost(created.getId(), deletePostReq));

        assertThat(updateErr.getReason()).isEqualTo("invalid password");
        assertThat(deleteErr.getReason()).isEqualTo("invalid password");
    }

    @Test
    public void 게시글삭제() {
        CreatePostReqDto post = new CreatePostReqDto("0000", "test", "testContents");
        PostResDto created = postService.createPost(post);

        PostReqDto deletePostReq = new PostReqDto(null, "0000", null);

        postService.deletePost(created.getId(), deletePostReq);

        ResponseStatusException e = assertThrows(ResponseStatusException.class, () -> postService.findPostById(created.getId()));

        assertThat(e.getReason()).isEqualTo("no post having id " + created.getId());
    }

    @Test
    public void 게시글좋아요() {
        CreatePostReqDto newPost = new CreatePostReqDto("0000", "test", "testContents");
        PostResDto post = postService.createPost(newPost);


        for (int i = 0; i < 100; i++) {
            post = postService.addPostLike(post.getId());
        }

        assertThat(post.getLikes()).isEqualTo(100);
    }

    @Test
    public void 없는id_get_update_delete() {
        CreatePostReqDto newPost = new CreatePostReqDto("0000", "test", "testContents");
        PostResDto post = postService.createPost(newPost);

        PostReqDto updatePostReq = new PostReqDto("patchTest", "0000", "patchTestContents");

        ResponseStatusException getErr = assertThrows(ResponseStatusException.class, () -> postService.findPostById(post.getId() + 1));
        ResponseStatusException updateErr = assertThrows(ResponseStatusException.class, () -> postService.updatePost(post.getId() + 1, updatePostReq));
        ResponseStatusException deleteErr = assertThrows(ResponseStatusException.class, () -> postService.deletePost(post.getId() + 1, updatePostReq));

        assertThat(getErr.getReason()).isEqualTo("no post having id " + (post.getId() + 1));
        assertThat(updateErr.getReason()).isEqualTo("no post having id " + (post.getId() + 1));
        assertThat(deleteErr.getReason()).isEqualTo("no post having id " + (post.getId() + 1));
    }
}
  • 게시글생성조회 -> post 를 생성한 후 받아온 id 로 게시글을 조회해 내용의 일치 여부를 판단

  • 게시글전체조회 -> 반복문을 사용하여 100개의 post 를 추가한 후 받아온 결과에서 totalElements, totalPage, 첫 번째 글의 내용을 검증

  • 게시글수정 -> post 생성 후 update 진행하고 다시 받아와 값 비교

  • patchAndDeleteException_invalidPassword -> 틀린 비밀번호로 delete, update 진행 후 exception 잡아서 getReason 비교

  • 게시글삭제 -> post 생성 후 delete 진행하고 해당 id 값이 조회되는지 확인

  • 게시글좋아요 -> post 생성 후 반복문 사용하여 100번 좋아요 요청 호출하고 값 확인

  • 없는id_get_update_delete() -> post 생성하고 받아온 id 와 다른 값을 사용해 조회 진행 후 getReason 확인

CommentServiceTest

package com.example.spring_board.service;

import com.example.spring_board.dto.comment.CommentReqDto;
import com.example.spring_board.dto.comment.CommentResDto;
import com.example.spring_board.dto.comment.CreateCommentReqDto;
import com.example.spring_board.dto.post.CreatePostReqDto;
import com.example.spring_board.service.comment.CommentService;
import com.example.spring_board.service.post.PostService;
import org.junit.jupiter.api.BeforeEach;
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 org.springframework.web.server.ResponseStatusException;

import java.util.List;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

@Transactional
@SpringBootTest
public class CommentServiceTest {

    @Autowired
    private CommentService commentService;
    @Autowired
    private PostService postService;

    private Long postId;

    @BeforeEach
    public void createPost() {
        CreatePostReqDto post = new CreatePostReqDto("0000", "test", "testContents");
        this.postId = postService.createPost(post).getId();
    }

    @Test
    public void 댓글생성조회() {
        CreateCommentReqDto createCommentReq = new CreateCommentReqDto("test", "0000", this.postId);
        Long id = commentService.createComment(createCommentReq).getId();

        Long commentId = commentService.findCommentById(id).getId();

        assertThat(id).isEqualTo(commentId);
    }

    @Test
    public void 게시글별댓글전체조회() {
        for (int i = 0; i < 100; i++) {
            CreateCommentReqDto createCommentReq = new CreateCommentReqDto("test" + i, "0000", this.postId);
            commentService.createComment(createCommentReq);
        }

        List<CommentResDto> comments = postService.findAllCommentsByPostId(this.postId);

        assertThat(comments.size()).isEqualTo(100);
        assertThat(comments.get(0).getContents()).isEqualTo("test99");
    }

    @Test
    public void 댓글수정() {
        CreateCommentReqDto createCommentReq = new CreateCommentReqDto("test", "0000", this.postId);
        CommentResDto created = commentService.createComment(createCommentReq);

        CommentReqDto updateReq = new CommentReqDto("patchTestContents", "0000");

        CommentResDto updated = commentService.updateComment(created.getId(), updateReq);

        assertThat(updated.getContents()).isEqualTo("patchTestContents");
    }

    @Test
    public void 댓글삭제() {
        CreateCommentReqDto createCommentReq = new CreateCommentReqDto("test", "0000", this.postId);
        CommentResDto created = commentService.createComment(createCommentReq);

        CommentReqDto deleteReq = new CommentReqDto(null, "0000");

        commentService.deleteComment(created.getId(), deleteReq);

        ResponseStatusException e = assertThrows(ResponseStatusException.class, () -> commentService.findCommentById(created.getId()));

        assertThat(e.getReason()).isEqualTo("no comment having id " + created.getId());
    }

    @Test
    public void 댓글좋아요() {
        CreateCommentReqDto createCommentReq = new CreateCommentReqDto("test", "0000", this.postId);
        CommentResDto created = commentService.createComment(createCommentReq);

        for (int i = 0; i < 100; i++) {
            created = commentService.addCommentLike(created.getId());
        }

        assertThat(created.getLikes()).isEqualTo(100);
    }

    @Test
    public void invalidPassword_update_delete() {
        CreateCommentReqDto createCommentReq = new CreateCommentReqDto("test", "0000", this.postId);
        CommentResDto created = commentService.createComment(createCommentReq);

        CommentReqDto deleteReq = new CommentReqDto(null, "1000");
        CommentReqDto updateReq = new CommentReqDto("patchTestContents", "1000");

        ResponseStatusException updateErr = assertThrows(ResponseStatusException.class, () -> commentService.updateComment(created.getId(), updateReq));
        ResponseStatusException deleteErr = assertThrows(ResponseStatusException.class, () -> commentService.deleteComment(created.getId(), deleteReq));

        assertThat(updateErr.getReason()).isEqualTo("invalid password");
        assertThat(deleteErr.getReason()).isEqualTo("invalid password");
    }

    @Test
    public void 없는id() {
        CreateCommentReqDto createCommentReq = new CreateCommentReqDto("test", "0000", this.postId);
        CommentResDto created = commentService.createComment(createCommentReq);

        ResponseStatusException e = assertThrows(ResponseStatusException.class, () -> commentService.findCommentById(created.getId() + 1));

        assertThat(e.getReason()).isEqualTo("no comment having id " + (created.getId() + 1));
    }
}
  • BeforeEach -> post.id 와 연결되는 DB 라 각 테스트 실행 전 createPost() 메서드 실행시켜 post 생성 후 id 필드에 할당

  • 댓글생성조회 -> comment 생성 후 받아온 id 로 조회하고 일치여부 확인

  • 게시글별댓글전체조회 -> 반복문 사용하여 comment 생성 후 size 와 첫 번째 값 일치 여부 확인

  • 댓글수정 -> comment 생성 후 받아온 id 로 update 진행 후 내용 확인

  • 댓글삭제 -> comment 생성 후 받아온 id 로 delete 진행 후 getReason 일치 여부 확인

  • 댓글좋아요 -> comment 생성 후 반복문으로 좋아요 요청 보내고 조회 후 일치 여부 확인

  • invalidPassword_update_delete -> comment 생성 후 잘못된 비밀번호로 delete, update 진행하고 err getReason 일치 여부 확인

  • 없는id -> comment 생성 후 받아온 id 와 다른 값을 사용해 조회 후 발생한 에러 getReason 일치 여부 확인

개선 사항

  1. service 테스트를 진행하며 service 메서드에 의존함 (예. createPost 를 테스트 하는 과정에서 findById 메서드를 사용해서 값을 조회)
  2. Transactional 을 사용해 DB 에 값이 남지는 않지만 AUTO_INCREMENT 된 id 값이 증가해있는 문제가 있음. MockDB 등을 사용해 해결할 수 있다.

0개의 댓글