작성
·
1.1K
3
@SpringBootTest
@AutoConfigureMockMvc
@PropertySource("classpath:messages.properties")
class PostControllerTest {
@Autowired
private ObjectMapper mapper;
@Autowired
private Environment environment;
@Autowired
private MockMvc mockMvc;
@Autowired
private PostRepository postRepository;
@BeforeEach
void clean() {
postRepository.deleteAll();
}
@Test
@DisplayName("/posts 요청시 Hello World를 출력한다.")
void test() throws Exception {
// given
PostCreate request = PostCreate.builder()
.title("제목입니다.")
.content("내용입니다.")
.build();
String json = mapper.writeValueAsString(request);
// expected
mockMvc.perform(MockMvcRequestBuilders.post("/posts")
.contentType(MediaType.APPLICATION_JSON)
.content(json)
// .content("{\"title\": \"hithere\", \"content\": \"blah\"}")
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string(""))
.andDo(print());
}
@Test
@DisplayName("/posts 요청시 title 값은 필수다.")
void test2() throws Exception {
Class<? extends PostControllerTest> aClass = getClass();
ClassLoader classLoader = getClass().getClassLoader();
URL resource = classLoader.getResource("messages.properties");
// given
PostCreate request = PostCreate.builder()
.content("내용입니다.")
.build();
String json = mapper.writeValueAsString(request);
// expected
mockMvc.perform(MockMvcRequestBuilders.post("/posts")
.contentType(MediaType.APPLICATION_JSON)
.content(json)
)
.andExpect(MockMvcResultMatchers.status().isBadRequest())
.andExpect(MockMvcResultMatchers.jsonPath("$.code").value("400"))
.andExpect(MockMvcResultMatchers.jsonPath("$.message").value("잘못된 요청입니다."))
.andExpect(MockMvcResultMatchers.jsonPath("$.validation.title").value(environment.getProperty("post.NotBlank")))
.andDo(print());
}
@Test
@DisplayName("/posts 요청시 db에 값이 저장된다.")
void test3() throws Exception {
// given
PostCreate request = PostCreate.builder()
.title("제목입니다.")
.content("내용입니다.")
.build();
String json = mapper.writeValueAsString(request);
// expected
mockMvc.perform(MockMvcRequestBuilders.post("/posts")
.contentType(MediaType.APPLICATION_JSON)
.content(json)
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(print());
// then
assertEquals(1L, postRepository.count());
Post post = postRepository.findAll().get(0);
assertEquals("제목입니다.",post.getTitle());
assertEquals("내용입니다.",post.getContent());
}
@Test
@DisplayName("글 1개 조회")
void test4() throws Exception {
// given
Post post = Post.builder()
.title("123456789012345")
.content("bar")
.build();
postRepository.save(post);
// when
// expected
mockMvc.perform(MockMvcRequestBuilders.get("/posts/{postId}",post.getId())
.contentType(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.id").value(post.getId()))
.andExpect(MockMvcResultMatchers.jsonPath("$.title").value("1234567890"))
.andExpect(MockMvcResultMatchers.jsonPath("$.content").value("bar"))
.andDo(print());
// then
}
@Test
@DisplayName("글 여러개 조회")
void test5() throws Exception {
// given
List<Post> requestPosts = IntStream.range(1,31)
.mapToObj(i ->
Post.builder()
.title("title " + i)
.content("content " + i)
.build()
).collect(Collectors.toList());
postRepository.saveAll(requestPosts);
// expected
mockMvc.perform(MockMvcRequestBuilders.get("/posts?page=1&sort=id,desc")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.length()",Matchers.is(5)))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].id").value(30))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].title").value("title 30"))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].content").value("content 30"))
.andDo(print());
}
}
안녕하세요 호돌맨님 질문이 있습니다.
test5를 단독으로 실행하면 문제없는데
전체를 실행했을 때는 postRepository.saveAll 전까지는 requestPosts 안에 Post가 id가 1부터 시작하는데
saveAll을 지나고 나서는 id가 4부터 시작하게됩니다.
@BeforeEach에서 postRepository.deleteAll을 수행하고 있습니다.
제생각에는
이게 Entity 의 @GeneratedValue(strategy = GenerationType.IDENTITY) 와 연관이 있는건가요?
해당 설정을 하면 말씀해주신것처럼 persist가 호출되는 시점에 id값을 db로부터 얻어오기 때문에 아무리 row가 지워졌어도 h2 내부적으로 id를1씩 증가시켜왔기에 그 증가된 값이 requestPosts 의 값도 변형시킨것이 맞나요?
답변 4
5
안녕하세요? 호돌맨입니다.
("requestPosts 안에 Post가 id가 1부터 시작하는데" 이 부분은 제가 이해하지 못했습니다. 작성하신 소스를 보면 requestsPosts의 Post데이터는 아직 id값 빌더를 통해 할당하지 않으셨기 때문에 Long 타입이라면 null이 들어가 있을것 같습니다.)
우선은 말씀하신 게 대체로 맞습니다. 정확히 @GeneratedValue(strategy = GenerationType.IDENTITY)
에 직접적으로 연관이 있다기 보다도
h2, mysql 기준으로 테이블 row를 삭제(postRepository.delete)한다고 해서 id(primary_key)가 1로 초기화 되지는 않습니다. id가 1로 초기화 되는 아래와 같습니다.
테이블이 삭제 되거나
테이블이 TRUNCATE 되거나
ALTER TABLE 명령어로 auto increment값을 1로 수정하거나
.andExpect(MockMvcResultMatchers.jsonPath("$[0].id").value(30))
위와같이 코드를 적더라도 id가 30이라고 보장 받을 수 없습니다.
왜냐하면 테스트가 실행되는 순서를 보장할 수 없기 때문입니다.
전체 테스트 실행시 위의 코드를 포함하는 테스트 메서드는 첫 빠따로 수행될수도 있고 마지막으로 수행될수도 있습니다.
그렇기 때문에 아래와같이 '요청한 데이터 의 id값인 requestsPosts.get(마지막index).id로 체크하는 게 좋아보입니다.
.andExpect(MockMvcResultMatchers.jsonPath("$[0].id").value(request.Posts.get(29인가 30인가).getId()))
감사합니다.
0
0
0
그렇군요 null이 들어가겠군요 제가 잘못봤습니다
빠른 답변 너무 감사합니다!!!!!!!!!!!