MockMvc 객체를 이용하여 Controller 테스트를 작성해보았다. 각각의 컨트롤러에 대해서 테스트 코드를 작성하고 테스트를 돌려보고, 테스트 코드 작성하고 돌려보고를 반복하였을 때는 모든 테스트 코드가 잘 돌아갔다.
하지만, 모든 테스트 코드를 한번에 돌렸을 때, 아래와 같이 몇개만 맞고 나머지는 모두 실패했다.
우선 테스트 코드는 다음과 같다. @BeforeEach를 통해 매 테스트 코드가 테스트 DB에 10개의 Post를 저장해주었다.
해당 클래스에 @Transactional을 걸어주었기 때문에, @BeforeEach도 매 테스트마다 롤백이 일어나 모든 테스트 케이스는 10개의 데이터로 테스트를 진행할 수 있다.
@BeforeEach
void beforeEach() {
Member member = memberRepository.save(new Member(1L, "test_username", passwordEncoder.encode("1234"),
"test_nickname", "test@email.com", 3L, LocalDateTime.now()));
List<Post> postList = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
postList.add(new Post((long) i, member, "subject %s".formatted(i),
"content %s".formatted(i), "contentHtml %s".formatted(i)));
}
postRepository.saveAll(postList);
}
아래와 같이 1L로 Post를 찾으면, 테스트 케이스가 만족할 것 같았다.. 해당 테스트 케이스만 실행했을 때는 성공이었다.
@Test
@DisplayName("글수정")
@WithMockUser(username = "test_username", password = "1234", roles = "USER")
void modify() throws Exception {
mockMvc.perform(post("/post/1/modify")
.param("subject", "modify subject")
.param("content", "modify content")
.param("postKeywordContents", "#key1 #key2"))
.andExpect(status().is3xxRedirection())
.andExpect(handler().handlerType(PostController.class))
.andExpect(handler().methodName("modify"))
.andExpect(redirectedUrlPattern("/post/**"));
Post findPost = postRepository.findById(1L).orElseThrow();
assertThat(findPost.getSubject()).isEqualTo("modify subject");
assertThat(findPost.getContent()).isEqualTo("modify content");
}
이유는 @BeforeEach에서 데이터를 10개씩 저장 되지만, Post의 Id는 Auto Increament로 인해 Id는 초기화 되지 않는다.
즉, 해당 테스트 케이스는 첫번째로만 실행이 되어야 성공되는 테스트 케이스이고, 2번째는 데이터베이스에 11~20의 id를 가지는 Post가 저장되기 때문에 매번 id가 1인 Post에 대해서 찾기 때문에 "해당 글이 존재하지 않는다" 예외가 발생한 것이다.
1) Pagable 이용하기
@Test
@DisplayName("글수정")
@WithMockUser(username = "test_username", password = "1234", roles = "USER")
void modify() throws Exception {
Page<Post> page = postRepository.findAll(PageRequest.of(0, 1));
Long id = page.getContent().get(0).getId();
mockMvc.perform(post("/post/%s/modify".formatted(id))
.param("subject", "modify subject")
.param("content", "modify content")
.param("postKeywordContents", "#key1 #key2"))
.andExpect(status().is3xxRedirection())
.andExpect(handler().handlerType(PostController.class))
.andExpect(handler().methodName("modify"))
.andExpect(redirectedUrlPattern("/post/**"));
Post findPost = postRepository.findById(id).orElseThrow();
assertThat(findPost.getSubject()).isEqualTo("modify subject");
assertThat(findPost.getContent()).isEqualTo("modify content");
}
Page<Post> page = postRepository.findAll(PageRequest.of(0, 1));
로 데이터베이스에 저장된 첫번째 데이터를 가져온 후 해당 Post의 Id 값을 가져왔다.구글링을 해본 결과,
2) auto-increment 값을 재지정
@AfterEach
void afterEach() {
this.entityManager
.createNativeQuery("ALTER TABLE post ALTER COLUMN `id` RESTART WITH 1")
.executeUpdate();
}
처음에는 Pagable를 사용하여 테스트 코드를 작성하였는데, 너무 반복적인 코드 작성과 각각의 테스트가 서로 의존이 되는 것 같아 2번째의 방법을 선택하여 테스트 코드를 작성하였다.