JUnit에서 Controller 테스트 코드 작성하기(정리)
많은 부분을 참조한 출처: http://thswave.github.io/java/2015/03/02/spring-mvc-test.html
맨 먼저 환경설정.
JUnit을 위한 기본적인 환경설정이 돼있다는 전제 하에
Mock 디펜던시가 필요하다.
아래 소스를 추가.
1 2 3 4 5 6 | <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.10.19</version> <scope>test</scope> </dependency> | cs |
컨트롤러 테스트는 서비스와 잘 연결됐는지 확인만 해주면 되기 때문에
데이터를 받아오는 것까진 굳이 확인해줄 필요없다.
(하는 부분까지 데이터를 받는 게 되지도 않았지만..)
비즈니스 로직은 Service와 DAO에서 확인하면 될 것이다.
먼저, 전체소스부터 보여주고 차례로 정리해보겠다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | @Transactional @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={ "file:src/main/resources/config/spring/context-*.xml" }) public class PracticeControllerTest { private static final Logger logger = LoggerFactory.getLogger(PracticeControllerTest.class); @Mock SecondTesteService secondTestService; @Mock FirstTestService firstTestService; @InjectMocks private PracticeTestController practiceTestController; private MockMvc mockMvc; private LoginDTO loginDTO; private Map<String, Object> params; private ModelAndView mv; public MockHttpSession session; public MockHttpServletRequest request; @Before public void setUp() throws Exception { searchParamVO = new SearchParamVO(); params = new HashMap<>(); mv = new ModelAndView(); loginDTO = new LoginDTO(); loginDTO.setGroupSeq("zorbaGroup"); loginDTO.setCompSeq("zorbaCompany"); loginDTO.setEmpSeq("1234"); session = new MockHttpSession(); session.setAttribute("loginDTO", loginDTO); request = new MockHttpServletRequest(); request.setSession(session); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request)); MockitoAnnotations.initMocks(this); mockMvc = MockMvcBuilders.standaloneSetup(practiceTestController).build(); } /* * 테스트 페이지 뷰 * */ @Test public void testChocolateView() throws Exception { Map<String, Object> paramMap = new HashMap<>(); paramMap.put("loginDTO", loginDTO); mockMvc.perform(get("/test/view").session(session)).andExpect(status().isOk()) .andExpect(view().name("/test/view/chocolate.jsp")); verify(secondTestService).getOPTION(paramMap); mv = practiceTestController.ChocolateView(searchParamVO, params, request); assertTrue(mv.getModel().containsKey("optionA")); // return 됐을 때 해당 키를 포함하고 있는지 확인 assertTrue(mv.getModel().containsKey("optionB")); assertTrue(mv.getModel().containsKey("loginDTO")); verify(secondTestService, times(1)).getOPTION(paramMap); verify(secondTestService, atLeastOnce()).getOPTION(paramMap); } /* * 테스트 리스트 조회 * */ @Test public void testGetChocolateList() throws Exception { mockMvc.perform(get("/test/getChocolateList").session(session)).andExpect(status().isOk()) // 상태 200이 되는지 검증 .andExpect(view().name("jsonView")); // 심어준 뷰 검증 mv = practiceTestController.GetChocolateList(params, request); verify(firstTestService).GetChocolateList(params); // 컨트롤러와 잘 연동되는지 검증 verify(firstTestService, times(1)).GetChocolateList(params); // 몇 번 호출되는지 검증 verify(firstTestService, atLeastOnce()).GetChocolateList(params); // 최소한 1번 이상 수행 검증 } } | cs |
이제부터 하나하나씩 뜯어보겠다.
1 2 3 4 5 6 7 8 | @Mock SecondTesteService secondTestService; @Mock FirstTestService firstTestService; @InjectMocks private PracticeTestController practiceTestController; | cs |
@Mock과 @InjectMocks이다.
@InjectMocks에 선언된 컨트롤러에 @Mock에 선언된 Service를 빈으로 주입한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public MockHttpSession session; public MockHttpServletRequest request; @Before public void setUp() throws Exception { searchParamVO = new SearchParamVO(); params = new HashMap<>(); mv = new ModelAndView(); loginDTO = new LoginDTO(); loginDTO.setGroupSeq("zorbaGroup"); loginDTO.setCompSeq("zorbaCompany"); loginDTO.setEmpSeq("1234"); session = new MockHttpSession(); session.setAttribute("loginDTO", loginDTO); request = new MockHttpServletRequest(); request.setSession(session); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request)); | cs |
Mock세션을 만드는 것은 여기 참조.
1 2 3 | MockitoAnnotations.initMocks(this); mockMvc = MockMvcBuilders.standaloneSetup(practiceTestController).build(); | cs |
MOckitoAnnotations.initMocks(this)이 @Autowired 역할을 수행한다.
standaloneSetup은 컨트롤러를 MockMvc 객체로 등록해준다.
1 2 | mockMvc.perform(get("/test/view").session(session)).andExpect(status().isOk()) .andExpect(view().name("/test/view/chocolate.jsp")); | cs |
get방식으로 request를 요청한 것이다.
.perform()을 이용하면 매핑url로 request한다. request에서 session을 심어주고 싶다면
.session으로 해서 담아주면 되고,
.andExpect를 이용해서 다양하게 검증할 수 있다.
status().isOk()는 상태가 200번을 내뱉는지, 400번 에러를 뱉는지 체크할 수 있고,
내가 담아주려한 view에 정확하게 담겼는지 확인할 수 있다. (그 외에도 다양한 검증방법이 있으니 찾아보면 됨)
1 2 3 4 5 | mv = practiceTestController.ChocolateView(searchParamVO, params, request); assertTrue(mv.getModel().containsKey("optionA")); // return 됐을 때 해당 키를 포함하고 있는지 확인 assertTrue(mv.getModel().containsKey("optionB")); assertTrue(mv.getModel().containsKey("loginDTO")); | cs |
Map형식으로 ModealAndView를 리턴할 때 해당 키를 포함하고 있는지 체크하는 방법이다.
ModelAndView.getModel().contatinsKey() 활용
1 2 | verify(secondTestService, times(1)).getOPTION(paramMap); verify(secondTestService, atLeastOnce()).getOPTION(paramMap); | cs |