잘못된 내용이나 더 나은 방식 등에 대한 의견은 댓글로 피드백 부탁드리겠습니다. :)
정리할 내용!
- MVC 기능 확인을 위한 Controller test
- 비즈니스 로직 구현 확인을 위한 service (logic) test
- 확인하고자 하는 단위 외의 영역은 stubbing 하기
- unit test를 작성하며 refactoring 을 진행하기
보이스카우트 원칙 : (클린코드 p18-19)
- 잘 짠 코드가 전부는 아니다. 시간이 지나도 언제나 깨끗하게 유지해야 한다.
- 변수 이름을 하나씩 개선
- 조금 긴 함수가 있다면 하나씩 분할
- 중복인 부분은 통합, 불필요 라인 제거
- 복잡한 if문 하나씩 정리
build - operate - check 패턴*으로 테스트 구성
구성 정리
/------ arrange ------/
String accountCode = "812000";
AccountingVO accountingVO = getTestAccountingVOForSearching(cd_account, "1"); // 검색조건 : 여비교통비, 집계구분 = 프로젝트
/------ act ------/
// 출력 데이터 조회
List<AccountingVO> printIncomeExpensesAllList = (List<AccountingVO>) incomeExpensesService.selectIncomeListForPrint(accountingVO);
/------ assert ------/
assertThat(printIncomeExpensesAllList.size(), is(9)); // list의 조회 수는 9개로 설정됨
// 조회된 sq_code 확인 = 1자리 수 (ex) 1 = 총괄 (cd_ 인 경우에는 2자리수 : 01)
assertThat(printIncomeExpensesAllList.get(0).getSq_code(), is(30L));
build : 테스트에 필요한 변수 설정
operate : 실제 테스트할 대상 로직
check : 로직결과나 로직에서 확인이 필요한 데이터에 대한 단언(assert). 예상된 값과 실제 생성 값의 비교
*Arrange - Act - Assert (AAA)로도 표현 가능
기타
@ModelAttribute("ObjectVO") ObjectVO objectVO
가 controller의 param으로 설정된 경우 parameter로 전달되는 항목을 ObjectVO class와 대응하여 변환이 처리됩니다.
Spring 4.0.3 버전 상에서는 여러 개의 param을 설정할 구문이 없는 상태로 확인됩니다.
Spring framework 4.3+ 부터는 tring key, String value
형식의 MultiValueMap
을 perform.params()
에 넣어 대응할 수 있다고 합니다.
객체 값을 param으로 설정할 대안을 찾다가... get 요청 uri 문자열을 구성하여 설정하고자 하는 parameter를 추가하는 식으로 대응하였습니다.
StringBuilder builder = new StringBuilder("/slip/getSlip.do?");
paramMap.forEach((key, value) -> {
if (value != null) {
builder.append("")
.append(key)
.append("=")
.append(value)
.append("&");
}
});
url = builder.toString();
url = url.substring(0, (url.length() - 1));
ResultActions perform = mockMvc.perform(post(url)
.session(mockSession));
MvcResult mvcResult = perform.andDo(print())
.andExpect(jsonPath("success").value(true))
.andReturn();
MockMvcRequestBuilders
의 get(), post()를 사용합니다.print()를 통해 나오는 결과는 다음과 같이 출력됩니다.
MockHttpServletRequest:
HTTP Method = POST
Request URI = /slip/getSlip.do
Parameters = {mode=[0], testParam1=[0], testParam2=[2], ...}
Headers = {}
Handler:
Type = ...
Method = ...
...
MockMvcResultMatchers.jsonPath 확인 시 아래의 예외 발생할 수 있습니다.
java.lang.NoClassDefFoundError: com/jayway/jsonpath/InvalidPathException
해당 예외가 발생되는 경우, jsonPath를 확인할 수 있도록 의존성을 추가하여아 합니다. (
com.jayway.jsonpath
주의할 점은, 최신 버전을 바로 적용할 수 없고 테스트 버전간 호환성 확인이 필요하다는 점입니다.
최신 버전을 적용 시 다음의 예외가 발생됨을 확인하였습니다.
// 2.4.0 버전으로 동작시 예외 발생
java.lang.NoSuchMethodError: com.jayway.jsonpath.JsonPath.compile(Ljava/lang/String;[Lcom/jayway/jsonpath/Filter;)Lcom/jayway/jsonpath/JsonPath;
Spring 4.0.3의 테스트 환경에서는 0.9.x 버전을 적용하여야 정상 동작하는 것으로 확인됩니다.
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>0.9.1</version>
</dependency>