[Java Spring] 내가 정한 테스트 코드의 목적성을 잃지 말자

김태훈·2023년 9월 3일
0
post-thumbnail
@ActiveProfiles("test") //test profile
@SpringBootTest
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@Sql("classpath:CommentRepository.sql")
class CommentRepositoryImplTest {
    @Autowired
    DataSource dataSource;
    @Autowired
    CommentRepository commentRepository;
    @BeforeEach
    void beforeEach(){
        Comment comment = new Comment(1L,
                new MemberProfileEntity("set_image_path","set_nickname","set_introduce","set_tag"),
                Date.valueOf(now()),
                null,
                new CommentSaveDto(PostType.MEMO,1L,"set_text"));
        commentRepository.createComment(comment);
    }

    @Test
    @WithMockCustomUser()
    @DisplayName("올바른 댓글 형식에서의 댓글 저장")
    void createValidComment(){
        Comment comment = new Comment(1L,
                new MemberProfileEntity("test_image_path","test_nickname","test_introduce","test_tag"),
                Date.valueOf(now()),
                null,
                new CommentSaveDto(PostType.MEMO,1L,"comment_text"));
        Authentication authentication = SecurityContextHolder.getContext()
                .getAuthentication();
        System.out.println("authentication = " + authentication);
        assertEquals(commentRepository.createComment(comment),2);
    }
}

나는 지금 Repository 계층 (Persistence Layer)의 단위테스트 (인메모리 DB를 띄워서 사실상 통합테스트 느낌이지만.. 결과적으로 서비스계층과의 결합성을 끊어냈으므로 단위테스트느낌이라고 생각했다)를 하고 있었다.
하지만 저 위에 테스트코드에서 잘못 생각했던 부분이 있었다.

바로 @WithMockCustomUser()이 부분이다.
왜 잘못되었을까?

나의 repository 관련 실제 구현코드는 다음과 같다.

package Funssion.Inforum.domain.post.comment.repository;

@Repository
@Transactional
@Slf4j
public class CommentRepositoryImpl implements CommentRepository{
    private final JdbcTemplate template;
    public CommentRepositoryImpl(DataSource dataSource){
        this.template = new JdbcTemplate(dataSource);
    }
    @Override
    public Long createComment(Comment comment) {
        KeyHolder keyHolder = new GeneratedKeyHolder();
        String sql = "insert into comment.info (author_id, author_image_path, author_name, post_type, post_id, comment_text, created_date)"
                + "values (?, ?, ?, ?, ?, ?, ?)";
        int updatedRow = template.update(con -> {
            PreparedStatement psmt = con.prepareStatement(sql, new String[]{"id"});
            psmt.setLong(1, comment.getAuthorId());
            psmt.setString(2, comment.getAuthorImagePath());
            psmt.setString(3, comment.getAuthorName());
            psmt.setString(4, String.valueOf(comment.getPostTypeWithComment()));
            psmt.setLong(5, comment.getPostId());
            psmt.setString(6, comment.getCommentText());
            psmt.setTimestamp(7, Timestamp.valueOf(LocalDateTime.now())); // 생성자에서부터 바꿔야할 필요 있음. 반드시 리뷰할것.
            return psmt;
        }, keyHolder);

        if (updatedRow != 1){
            throw new CreateFailException("댓글 저장에 실패하였습니다.");
        }
        return keyHolder.getKey().longValue();
    }
}

Repository 계층에는 딱 DB와 관련된 내용만 들어가야만 했다.
그렇다면 MockUser 테스트를 할 필요가 없었다.
왜냐하면, 진작 Service 계층(Business Layer)에서 해당 코드를 포함하였기 때문에, repository 테스트를 하는데 굳이 authentication 객체의 mocking이 필요가 없기 때문이다.

profile
기록하고, 공유합시다

0개의 댓글