Whiteship's Note

[수정]AbstractModelAndViewTests 사용하여 Controller 테스트하기



이전 글에서 내렸던 결론은 좀 더 생각해보니 확실히 틀렸습니다.

테스트를 할 단위가 컨트롤러 전체 범위라면 이전 글의 가정이 맞겠지만 하나의 테스트는 최소한 작은 부분을 테스트 하라고 했었습니다. 컨트롤러에는 다양한 종류의 lifecycle 메소드들이 있으며 그것들을 전부 handleRequest의 결과인 ModelAndView를 사용하여 테스트 한다는 것은 다소 위험한 발상인 것 같습니다.

Controller 테스트 != ModelAndView 테스트


따라서 handleRequest 전체가 아닌 onSubmit()이 테스트의 대상이 되어야 합니다. 하지만 이전 글에서는 handleRequest를 가지고 테스트를 했었습니다.

이것을 다음과 같이 수정할 수 있습니다.

public class CheckControllerTest extends AbstractModelAndViewTests{

    private CheckController controller;
    private MemberService mockMemberService;
    private String mail;
    private MemberCommand command;

    public void setUp() {
        mockMemberService = createMock(MemberService.class);
        controller = new CheckController();
        controller.setMemberService(mockMemberService);
        command = new MemberCommand();
    }

    public void testEmptyOrWhiteMail() throws Exception {
        mail = "";
        expect(mockMemberService.findByMail(mail)).andReturn(null);
        replay(mockMemberService);
        command.setMail(mail);
        ModelAndView mav = controller.onSubmit(null, null, command, null);
        assertEquals("redirect:join.html", mav.getViewName());
        assertViewName(mav, "redirect:join.html");
        verify(mockMemberService);
    }

    public void testExistMemberMail() throws Exception {
        Member member = new Member();
        mail = "keesun@mail.com";
        member.setMail(mail);
        member.setName("기선");

        expect(mockMemberService.findByMail(mail)).andReturn(member);
        replay(mockMemberService);
        command.setMail(mail);
        ModelAndView mav = controller.onSubmit(null, null, command, null);
        assertViewName(mav, "confirm");
        assertModelAttributeValue(mav, "member", member);
    }
}

이전 테스트와의 가장 큰 차이점은 먼저 handleRequest 전부가 아닌 obSubmit 메소드만을 테스트 했다는 것입니다. 이래야 이전 보다 더 세부적인 부분을 테스트 했기 때문에 좀 더 단위 테스트라 부를 만 한 것 같습니다.

또하나 차이점은 MockHttpServletRequest와 MockHttpServletResponse의 필요가 없어졌습니다. Requet에 바인딩할 데이터를 주는 대신에 command 객체를 사용하여 이미 바인딩 된 상태라고 가정을 했습니다. 이전 테스트의 경우 binder를 사용하여 request에 넣어준 데이터를 바인딩하는 과정까지 테스트를 하는 것이였기 때문에 지금보다 훨씬 넓은 범위를 테스트 했다고 느껴집니다.

top