MockMVC를 통한 Springboot 통합 테스트를 작성해 보았다.
테스트 환경 세팅
// 부트가 실행될때와 같이 componentScan을 해와서 bean 세팅
@SpringBootTest
// Mock 객체의 자동 bean 주입을 해주는 어노테이션
@AutoConfigureMockMvc
class ArticleControllerTest {
@Autowired
MockMvc mockMvc;
@Autowired
private ObjectMapper mapper;
@Autowired
private WebApplicationContext context;
@Autowired
private ArticleRepository repository;
//MockMvc 객체의 서블릿과 컨트롤러를 재정의 하고싶으면 아래와 같이 builder 로 재정의 가능하다.
@BeforeEach
void mockSetUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
}
@AfterEach
void clean() {
repository.deleteAll();
}
MockMvc의 내부에는 testDispatcherServlet이 필드로 존재한다. 이는 @AutoConfigureMockMvc를 통해 의존성이 주입되지만 MockMvcBuilders를 통해 특정 환경으로 재정의도 가능하다.
Servlet의 정의뿐 아니라 Controller 단위로도 builder에서 세팅이 가능하다.
MockMvc 내부 구조
public final class MockMvc {
static final String MVC_RESULT_ATTRIBUTE = MockMvc.class.getName().concat(".MVC_RESULT_ATTRIBUTE");
private final TestDispatcherServlet servlet;
private final Filter[] filters;
private final ServletContext servletContext;
...이하 생략
}
생성 테스트
@DisplayName("생성 테스트")
@Test
public void testPost() throws Exception {
//given
String url = "/api/article";
ArticleRequest req = new ArticleRequest();
req.setTitle("testTitle");
req.setContent("testContent");
// RequestDto를 Json 타입으로 변환
String requestBody = mapper.writeValueAsString(req);
//when
//MockMvc 요청
ResultActions resultActions = mockMvc.perform(
post(url)
.contentType(MediaType.APPLICATION_JSON)
.content(requestBody)
);
//Service 로직
List<ArticleResponse> all = service.findAll();
//then
//Mock 검증 (Json 타입으로 반환되는 응답을 검증할 수도 있음)
resultActions.andExpect(status().isCreated());
//Junit 검증
assertThat(all.get(0).getTitle()).isEqualTo("testTitle");
assertThat(all.get(0).getContent()).isEqualTo("testContent");
}
mockMvc.perform() 메서드에 Request 객체를 build 하여 테스트 요청을 넣으면
검증이 가능한 ResultActions 객체를 반환한다.
Request는 Http메서드, 컨텐츠 타입, 바디값, 쿠키, 해더 등등 Http 요청에 포함되는 값들을 세팅할 수 있다.
기타 테스트 코드
@DisplayName("글 수정")
@Test
public void update() throws Exception {
//given
String url = "/api/article/{articleId}";
Article save = repository.save(
Article.builder()
.title("test1")
.content("test1")
.build());
UpdateArticleRequest updateArticleRequest = new UpdateArticleRequest();
updateArticleRequest.setTitle("newTest");
updateArticleRequest.setContent("newContent");
//when
ResultActions resultActions = mockMvc.perform(
put(url,save.getId())
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsString(updateArticleRequest))
);
//then
resultActions
.andExpect(status().isOk());
Article article = repository.findById(save.getId()).orElseThrow();
assertThat(article.getId()).isEqualTo(save.getId());
}
@DisplayName("글 삭제")
@Test
public void deleteArticle() throws Exception {
//given
String url = "/api/article/{articleId}";
Article save = repository.save(
Article.builder()
.title("test1")
.content("test1")
.build());
//when
ResultActions resultActions = mockMvc.perform(delete(url, save.getId()));
resultActions.andExpect(status().isNoContent());
List<Article> articles = repository.findAll();
//then
assertThat(articles).isEmpty();
}
@DisplayName("글 조회")
@Test
public void getAll() throws Exception {
//given
String url = "/api/article";
repository.save(
Article.builder()
.title("test1")
.content("test1")
.build());
//when
ResultActions resultActions = mockMvc.perform(
get(url)
.contentType(MediaType.APPLICATION_JSON)
);
//then
resultActions
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].title").value("test1"))
.andExpect(jsonPath("$[0].content").value("test1"));
}
'JUnit, TDD , 클린코드 연습' 카테고리의 다른 글
| 프로젝트 테스트 코드 작성 (0) | 2024.04.27 |
|---|---|
| 문자열 계산기 (0) | 2023.02.09 |

