자바 프로그래밍 6주차 학습일지

1. 학습한 내용 정리

이번 주에는 JUnit을 이용한 테스트 코드 작성 방법과 Spring Boot 환경에서의 MockMvc 활용법을 학습하였다.
각 테스트는 서로 영향을 주지 않도록 테스트 실행마다 독립적인 인스턴스로 수행되며,
테스트의 구조를 명확히 하기 위해 given - when - then 패턴을 사용하였다.
테스트 라이프사이클 관련 어노테이션을 사용하여 테스트 실행 전후의 초기화 및 정리 작업을 관리하는 방법을 배웠다.
JSON 응답을 검증하기 위해 jsonPath를 활용하였고,
MockMvc를 통해 실제 서버를 띄우지 않고도 HTTP 요청/응답 테스트가 가능함을 실습하였다.

2. 작성한 핵심 코드 설명

아래 코드는 Spring Boot 환경에서 Controller 계층의 API를 테스트하기 위해 작성한 JUnit 테스트 코드이다.
MockMvc를 이용하여 엔드포인트를 호출하고, 정상적인 응답과 데이터가 반환되는지를 검증한다.
@SpringBootTest @AutoConfigureMockMvc class TestControllerTest { @Autowired protected MockMvc mockMvc; @Autowired private WebApplicationContext webApplicationContext; @Autowired protected MemberRepository memberRepository; @Autowired private ObjectMapper objectMapper; @BeforeEach public void mockMySetup() { mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); } @DisplayName("전부 가지고 오는 api 테스트") @Test void getAllMembers() throws Exception { final String url = "/members"; Member saved = memberRepository.save(new Member(null, "seo")); final ResultActions result = mockMvc.perform(get(url).accept(MediaType.APPLICATION_JSON)); result.andExpect(status().isOk()) .andExpect(jsonPath("$[0].id").value(saved.getId())) .andExpect(jsonPath("$[0].name").value(saved.getName())); } @DisplayName("데이터 추가") @Test void create() throws Exception { final String url = "/member"; String memberName = "seoTest"; Member _member = memberRepository.save(new Member(memberName)); String _strBody = objectMapper.writeValueAsString(_member); final ResultActions _result = mockMvc.perform( post(url) .contentType(MediaType.APPLICATION_JSON) .content(_strBody)); _result.andExpect(status().isOk()) .andExpect(jsonPath("$.res").value("success")) .andExpect(jsonPath("$.data.name").value(memberName)); } @DisplayName("하나 가지고 오는 api test") @Test void getMemberById() throws Exception { final String url = "/member/{id}"; Member saved = memberRepository.save(new Member("seo")); final Long memberId = saved.getId(); final ResultActions result = mockMvc.perform(get(url, memberId).accept(MediaType.APPLICATION_JSON)); result.andExpect(status().isOk()) .andExpect(jsonPath("$.res").value("success")) .andExpect(jsonPath("$.data.id").value(saved.getId())) .andExpect(jsonPath("$.data.name").value(saved.getName())); } @DisplayName("하나 지우는 api") @Test void deleteMember() throws Exception { final String url = "/member/{id}"; Member saved = memberRepository.save(new Member("seo")); final Long memberId = saved.getId(); final ResultActions result = mockMvc.perform(delete(url, memberId)); result.andExpect(status().isOk()) .andExpect(jsonPath("$.res").value("success")) .andExpect(jsonPath("$.msg").value("delete Member OK id : " + memberId)); } }
Java
복사

3. 오류 해결 과정 및 주의사항

1.
ObjectMapper 관련 오류
JSON 직렬화 시 objectMapper.writeValueAsString() 누락 → 400 Bad Request
해결: 요청 본문(content)에 직렬화된 문자열을 넣도록 수정
2.
엔드포인트 경로 불일치 오류
@PostMapping("/member")와 테스트 요청 URL 불일치로 404 발생
해결: Controller의 매핑 경로와 테스트 URL을 동일하게 유지
3.
독립적 테스트 실행 주의
테스트마다 MockMvc를 @BeforeEach에서 초기화
테스트 데이터가 섞이지 않도록 매번 새로운 엔티티 저장
4.
응답 검증 시 jsonPath 경로 오류
잘못된 JSON 경로 사용 시 테스트 실패
해결: 실제 응답 구조를 확인한 뒤 정확한 경로 지정

4. 연습문제

1.
JUnit
2.
given - 저장할 새로운 메뉴 정보를 생성한다. when - 저장할 새로운 메뉴를 저장한다. then - 저장된 메뉴 정보가 given에서 준비한 메뉴 정보와 같은지 검증한다.
3.
@BeforeAll → @BeforeEach → @Test → @AfterEach → @AfterAll
4.
assertThat(a + b).isEqualTo(sum);
5.
HTTP 응답 코드가 201이며, 반환된 배열의 0번째 요소의 id가 15인지 검증하는 코드