ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JUnit에서 Controller 테스트 코드 작성하기(정리)
    웹 개발/Spring Framework 2018. 6. 18. 13:46


    많은 부분을 참조한 출처: 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


    verify()는 서비스가 컨트롤러에 잘 연동되고 동작하는지 검증하기 위한 메서드로 사용했다.

    time(int 값)은 컨트롤러에서 해당 메서드를 몇 번 수행하는지 체크하기 위함이다.

    verify(secondTestService, atLeastOnce()) 에서 atLeastOnce()는 

    메서드가 한 번 이상 수행했는지 검증해준다.

    동작하는지 안하는지만 보고 싶다면 atLeastOnce만 검증해도 될 것 같다.


    컨트롤러 테스트 끝~


Designed by Tistory.