그전에 알아야 할 것
Spring Test
- 스프링 프레임워크에서 제공하는 통합 테스트 및 스프링 MVC 통합 테스트 지원
Junit
- 단위 테스트 도구
- 단정문으로 테스트 케이스의 수행 결과를 판단
assetEquals(예상값, 실제값)
Mock
- 실제 객체를 만들기엔 비용과 시간이 많이 들거나 의존성이 길게 걸쳐져있어 제대로 구현하기 어려울 경우 가짜 객체를 만들어 사용
-> 가짜 객체
단위 테스트
- 하나의 기능 또는 메서드를 기준으로 독립적으로 진행되는 가장 작은 단위의 테스트
- 특징
- 빠름
- 문제 원인 파악이 쉬움
- Mock 사용이 많음
- 한계
- 실제 환경과 다름
- 여러 컴포넌트가 연결되었을 때 발생하는 문제는 탐지 불가
테스트 코드 작성 규칙
- 1개의 단위 테스트를 3가지 단계로 나누어 처리하는 패턴
- given(준비) : 어떠한 데이터가 준비되었을 때
- when(실행) : 어떠한 메서드를 실행하면
- then(검증) : 어떠한 결과가 나와야 함
통합 테스트
- 스프링 어플리케이션의 여러 계층(Controller, Service, Repository)을 실제처럼 묶어서 테스트 하는 것
- 스프링 컨텍스트를 실제로 띄우고 DB, Bean 주입까지 구성한 상태에서 전체 기능 흐름을 테스트
통합 테스트 특징
- 실제 환경과 매우 유사
a. 어플리케이션 전체 빈이 실제로 올라감
b. Mock이 아니라 Repository와 Service 사용 가능
- 단점
a. 느림 -> SpringBoot가 실제로 기동되어서 시간이 오래 걸림
b. 문제 원인 파악이 어려울 수 있음 -> 많은 계층이 있어 어디서 오류 났는지 찾기 복잡할 수 있음
MockMvc ResultAction
- MockMvc를 사용하여 HTTP 요청을 실행
post(), get() : HTTP 메서드를 결정
contentType() : 요청의 Content-Type 설정
param(), params() : 쿼리 파라미터 추가
mockMvc.perform(get("/users"))
.param("pageNumber", 0)
.param("pageSize", 5)
.andExpect(status().isOk());
2. .andExpect(ResultMatcher)
- 응답값과 기대값을 검증하는 메서드
status().is.Ok() → HTTP 상태 코드 검증
jsonPath(”$.필드”).value(”값”)
mockMvc.perform(post("/login"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.content.email").value("seo@jun.com"));
3. .andDo(ResultHandler)
- 결과를 출력하거나 로그 남기고 싶을 때 사용
- print()
mockMvc.perform(post("/login"))
.andDo(print())
.andExpect(status().isOk());
4. .andReturn()
- 요청 수행 후 MvcResult 객체를 얻고 싶을 때 사용
- 세션을 확인한다거나, 응답 Json을 직접 꺼낼 때 필요함
MvcResult result = mockMvc.perform(post("/login"))
.andExpect(status().isOk())
.andReturn();
String json = result.getResponse().getContentAsString();
MockHttpSession session = (MockHttpSession) result.getRequest().getSession();
실험 코드
로그인 테스트
@DisplayName(value = "로그인 및 로그아웃 테스트")
@Test
void loginTest() throws Exception {
User user = new User("seo@jun.com", "이서준", encoder.encode("test"));
userRepository.save(user);
String json = "{ \"email\":\"seo@jun.com\", \"password\":\"test\"}\"";
MvcResult result = mockMvc.perform(post("/login")
.contentType(MediaType.APPLICATION_JSON)
.content(json))
.andExpect(status().isOk())
.andExpect(jsonPath("$.content.id").value(1L))
.andExpect(jsonPath("$.content.email").value("seo@jun.com"))
.andReturn();
MockHttpSession session = (MockHttpSession) result.getRequest().getSession();
Assertions.assertNotNull(session);
SessionUser sessionUser = (SessionUser) session.getAttribute("loginUser");
Assertions.assertNotNull(sessionUser);
assertEquals("seo@jun.com", sessionUser.getEmail());
}
perform() : MockMvc를 사용하여 HTTP 요청을 실행
.andExpect(status().isOk()) : 상태 코드 OK 확인 틀리면 테스트 실패
.andExpect(jsonPath("$.content.id").value(1L)) : 응답 바디에 루트-> content->id의 값이 1이 아니면 테스트 실패
Assertions.assertNotNull(sessionUser) : sessionUser가 nul이면 테스트 실패 null이 아니면 테스트 통과