Spring MVC 리팩토링 4
이전에서 단위테스트를 통해 Controller과 Service, DAO 계층을 테스트 했습니다.
사실 DAO 계층 테스트를 단위테스트라고 할 수 있을지 모르겠지만 테스트용 DB와 테스트 데이터를 별로도 사용해서 실제 DB에는 전혀 지장이 없었습니다. 그리고 spring-mock.jar에 있는 AbstractTransactionalDataSourceSpringContextTests를 사용하여 자동 롤백이 되도록 하여 테스트의 흔적이 테스트 DB에 남지도 않았습니다. 그러면서도 DAO를 충분히 테스트 할 수 있었습니다.
이제는 Service Layer에서 DAO 계층과 함꼐 테스트를 해보고 그 다음은 Controller 에서 그 아래에 있는 Service 계층과 DAO 계층을 아울러서 테스트 할 차례입니다.
먼저 위 그림의 파란색은 이전에 테스트를 했고 빨간색 부분의 테스트를 작성합니다. 이 때도 이전 글에서 사용한 osaf의 클래스를 사용합니다.
protected MemberService memberService;
@Override
protected String[] getConfigLocations() {
return new String[] {
"file:web/WEB-INF/spring/applicationContext-dao.xml",
"file:test/applicationContext-jdbc-datasource.xml",
"file:web/WEB-INF/spring/dao/daoContext-member.xml",
"file:web/WEB-INF/spring/application/applicationContext-member.xml",
};
}
@Override
protected void onSetUpInTransaction() throws Exception {
insertFlatXmlDataSet("test/kr/co/springframework/member/dao/memberData.xml");
}
public void testDI() throws Exception {
assertNotNull(memberService);
}
public void testGetAll() throws Exception {
assertEquals(1, memberService.getAll().size());
}
public void testNotJoinedMail() throws Exception {
Member member = memberService.isJoined("");
assertEquals(null, member);
assertEquals("기선", memberService.isJoined("keesun@mail.com").getName());
}
}
간단하게 테스트 할 수 있습니다. 단위 테스트하고의 차이는 Spring의 컨테이너를 사용하여 의존성이 삽입된 객체를 사용하고 있으며 DB역시 DBUnit을 이용하여 사용하고 있습니다. 테스트용 DB라는 것만 빼고는 전부 같습니다. 아... 테스트용 DB(HSQL)와 실제 개발 DB(MySQL)와 다르군요. 하지만 ORM(하이버네이트)를 사용하고 있기 때문에 전~혀 문제가 없습니다. 테스트용 database.properties 파일 하나만 작성해주면 되죠.
이번에는 컨트롤러를 테스트 합니다. 이것도 역시 이전에 파란색 박스는 테스트를 했고 이번에는 빨간 박스를 테스트 합니다.
mail = "";
MemberCommand command = new MemberCommand();
command.setMail(mail);
mav = checkController.onSubmit(null, null, command, null);
assertEquals("redirect:join.html", mav.getViewName());
}
public void testExistMemberMail() throws Exception {
mail = "keesun@mail.com";
mav = checkController.onSubmit(null, null, command, null);
Map model = mav.getModel();
assertNotNull(model.get("member"));
assertEquals("confirm", mav.getViewName());
}
서비스 계층의 통합 테스트 코드와 상당부분이 같기 때문에 테스트 메소드만 붙여넣었습니다. (테스트 코드에서만 볼 수 있는)단위 테스트와의 차이는 easymock의 사용이 없어졌다는 것입니다. 이전에는 MemberService의 Mock객체를 만들어 사용했었습니다. 하지만 이제는 진짜 MemberSerive 객체를 사용하고 있죠.
이것으로 매~~~우 간단한 리팩토링(메소드 이름 하나 바꾸는 것)을 매우 길~~~~게 돌아오며 테스트를 연습해 봤습니다.
- Easy Mock은 생각보다 간단하다.(createMock() -> expect() -> replay() -> verify() -> reset())
- spring-mock.jar 에 유용한 Mock 객체들(Spring MVC 책에서는 Stub이라고 얘기하고 있지만)이 많이 있는데 그 중에 자주 사용할 것은 MockHttpServletRequest와 MockHttpServletResponse
- 계층 별 테스트 할 대상, 목록, 요점을 명확히 해야겠다.
- 테스팅(단위 테스트와 통합 테스트)은 확실히 애플리케이션에 자신감을 불어넣어준다.
- View를 테스트 하는 방법은 무엇일까? (Spring view test라고 구글링을 해봤지만 원하는 결과는 못봤다.)
- 컨트롤러를 테스트 할 때 데이터 바인딩과 벨리데이션 역시 테스트 해야겠다.
- 테스트 코드를 작성할 때 참고할 명세서가 있어야겠다.(비즈니스 로직을 자세히 설명한 어떤 문서...)