Spring Boot 기반의 웹 프로그램에서 JUnit5 , MockMvc 를 이용하여 테스트를 진행하는 방법입니다
JUnit5 테스트를 위한 기본 소스
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
@SpringBootTest
@AutoConfigureMockMvc
public class ControllerTest {
@Autowired
private MockMvc mvc;
@Test
public void callTest() throws Exception{
- 생략 -
}
}
위에는 가장 기본적인 예제입니다
@SpringBootTest 를 선언해서 해당 클래스가 Spring Boot 테스트 진행을 위한 클래스라는걸 선언하고
@AutoConfigureMockMvc 를 통해 Spring Boot 에서 사용되는 여러 설정(@Service 등) 을 사용하도록 선언합니다
MockMvc 를 이용해 테스트를 진행하고
@Test 선언을 통해 해당 메소드가 테스트 메소드라고 선언합니다
서버 동작을 위한 프로퍼티 설정
@SpringBootTest(properties = {"classpath:/application.yml", "spring.profiles.active=abcd"})
다음으로 Spring Boot 실행 시 별도의 설정이 필요할 경우 @SpringBootTest 의 properties 속성을 통해 설정할 수 있다
만약 서버 실행 시 -Dspring.profile.active=abcd 라는 설정이 필요하다면 위에처럼 사용할 수 있다
GET 방식의 호출 JUnit5 테스트
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.result.MockMvcResultMatchers.status;
@Test
@DisplayName("GET 방식 테스트")
public void callGetTest() throws Exception{
this.mvc.perform(get("/main"))
.andExpect(status().isOk());
}
브라우저에서 http://도메인/main 이란 URL 을 호출하는 테스트다
응답으로 200 code 가 리턴되면 JUnit5 테스트가 정상 완료된다
이처럼 모든 테스트는 MockMvc 를 이용하여 진행된다
GET 방식 호출 후 리턴되는 view 이름으로 테스트
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
@Test
@DisplayName("GET 방식 테스트")
public void callGetTest() throws Exception{
this.mvc.perform(get("/main"))
.andExpect(status().isOk())
.andExpect(view().name("main/page"));
}
컨트롤러에서 뷰 이름을 String 타입으로 리턴할 때 테스트하는 방식이다
Redirect 응답 시 테스트
import static org.springframework.test.web.servlet.result.MockMvcREsultMatchers.redirectedUrl;
@Test
@DisplayName("GET Redirect 방식 테스트")
public void callGetTest() throws Exception{
this.mvc.perform(get("/main"))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrl("/abcd/efg"));
}
특정 URL 호출 시 경우에 따라 다른 주소로 Redirect 될 때 테스트하는 방식이다
CSRF 토큰 필요 시 테스트
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
@Test
@DisplayName("CSRF 토큰 테스트")
public void callCsrfTest() throws Exception{
this.mvc.perform(post("/main").with(csrf()))
.andExpect(status().isOk());
}
내부적으로 Spring Security 를 사용하고 있고 CSRF 토큰을 이용하고 있다면 경우에 따라 CSRF 토큰도 함께 포함해서 요청해야 할 수도 있다.
만약 csrf() 를 제외할 경우 403 응답으로 수신된다
JUnit5 요청/결과 내용 보기
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
@Test
@DisplayName("GET 방식 테스트")
public void callGetTest() throws Exception{
this.mvc.perform(get("/main"))
.andExpect(status().isOk())
.andDo(print());
}
테스트 중 JUnit5 에서 어떤식으로 요청을 보냈고 어떤 응답을 받았는지 보고싶을 수 있다
이때 andDo(print()) 를 추가해주면 콘솔에서 확인해볼 수 있다
트랜잭션 테스트
import org.springframework.transaction.annotation.Transactional;
@Test
@Transactional
@DisplayName("트랜잭션 방식 테스트")
public void callInsertTest() throws Exception{
this.mvc.perform(post("/add"))
.andExpect(status().isOk())
.andDo(print());
}
JUnit5 를 이용해 등록/변경 테스트 시 실제로 데이터베이스에 데이터가 등록되거나 변경이 되면 안된다
이럴 경우 @Transactional 를 선언해주면 테스트 완료 후 롤백처리된다
요청 시 파라미터 추가 방법
@Test
@Transactional
@DisplayName("파라미터 방식 테스트")
public void callInsertTest() throws Exception{
this.mvc.perform(post("/add")
.param("name", "홍길동")
.param("age", "11"))
.andExpect(status().isOk())
.andDo(print());
}
JUnit5 를 통해 Get, Post, Put 등의 메소드로 컨트롤러 호출 시 파라미터를 추가할 때가 있다
이때는 param 메소드를 통해 추가하면 된다
예외 응답 처리
@Test
@Transactional
@DisplayName("예외 발생 테스트")
public void callExceptionTest() throws Exception{
org.assertj.core.api.Assertions.assertThatThrownBy(()->
this.mvc.perform(post("/add")
.param("name", "홍길동")
.param("age", "11"))
.andExpect(status().isOk())
.andDo(print())
).hasCause(new NullPointerException());
}
개발자의 구현 방식에 따라 강제로 예외를 발생시키는 경우도 있다
만약 위의 호출에서 NullPointerException 이 발생하는게 정상일 경우 위의 방식처럼 호출하면 된다
만약 NullPointerException 안에 별도의 문구도 있다면 동일하게 문구까지 설정해줘야한다
로그인이 필요한 요청 호출
import org.springframework.security.test.context.support.WithUserDetails;
@Test
@WithUserDetails(userDetailsServiceBeanName = "testUser")
@Transactional
@DisplayName("로그인 필수 요청 호출 테스트")
public void callInsertTest() throws Exception{
this.mvc.perform(post("/add")
.param("name", "홍길동")
.param("age", "11"))
.andExpect(status().isOk())
.andDo(print());
}
@Service
public class testUser implements UserDetailsService{
@Override
public UserDetials loadUserByUsername(username) throws UsernameNotFoundException{
- 생략 -
return xx;
}
}
대부분의 요청은 로그인 상태에서만 유효하다
이런 테스트를 위해 @WithUserDetials 를 선언하여 로그인 상태의 서비스를 이용할 수 있다
여기까지 Spring Boot 환경에서 JUnit5 와 MockMvc 를 이용한 테스트를 마무리한다
참고 솔루션 : 봄즈
'봄보라' 카테고리의 다른 글
Spring Boot 에서 JUnit5 , MockMvc 를 이용하여 JSon 응답 값 검증하기 (0) | 2021.12.12 |
---|---|
Spring Boot 도커 배포를 위해 Gitlab CI/CD 이용하기 (0) | 2021.11.07 |
MariaDB Sequence 사용하기 (0) | 2021.10.24 |
Kanban(칸반) 시작을 위한 가이드 (0) | 2021.10.17 |
XSS 공격 방지를 위한 OWASP ESAPI 이용하기 (0) | 2021.10.10 |