day 08

유요한·2022년 12월 19일
1

Spring

목록 보기
11/15
post-thumbnail

day 07에서 하지 못했던 userService test를 해주려고 합니다.

package com.example.service;

import com.example.domain.UserDTO;
import lombok.Setter;
import lombok.extern.log4j.Log4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class UserServiceTest {
    @Setter(onMethod_ = @Autowired)
    private UserService service;

    @Test
    public void joinTest() {
        UserDTO user = new UserDTO();
        user.setUserId("testId2");
        user.setUserPw("testPw2");
        user.setUserName("testName2");

        log.info("result : " + service.join(user));
    }

    @Test
    public void loginTest() {
        log.info("result : " + service.login("testId2", "testPw2"));
    }
}

userMapper와 userService도 만들어주고 테스트까지 끝났으니 userController로 돌아와서 코드를 완성 시켜줍니다.

먼저 service테스트가 성공적으로 끝났으니 UserService를 생성해줍니다.

@Setter(onMethod_ = @Autowired)
    UserService service;

@PostMapping("/join") 코드를 적어주기 전에 이 어노테이션과 메소드는 회원가입시 post형식으로 보내주는 것을 cookie나 session 등에 담아서 보여줄 수 있습니다. `


day07과 day08 초반부까지 완료한다면 다음과 같은 화면이 됩니다.

회원가입을 누르면 다시 스프링 게시판 화면이 나옵니다.

컨트롤러를 만들때마다 서버를 키고 다시 하는 것은 번거롭습니다. 그렇기 때문에 테스트에서 확인하는 것이 편합니다.

package com.example.controller;

import lombok.Setter;
import lombok.extern.log4j.Log4j;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.ModelAndView;

@RunWith(SpringJUnit4ClassRunner.class)
@Log4j
@ContextConfiguration(
        {
                "file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml",
                "file:src/main/webapp/WEB-INF/spring/root-context.xml"
        })
// Spring Framework에서 애플리케이션 컨텍스트의 웹 버전을 생성하는 데 사용되는 클래스 레벨 어노테이션입니다.
@WebAppConfiguration
public class UserControllerTest {
    @Setter(onMethod_ = @Autowired)
    private WebApplicationContext wac;
    // web 관련된 spring MVC가 필요한데 그걸 실행하려면 서버를 실행해야 한다.
    // 테스트할때는 서버를 실행하지 않기 때문에 MockMvc라는 것이 필요하다.
    // 테스트를 위해 브라우저나 WAS의 동작을 똑같이 처리해줄 수 있는 환경이다.
    // 가짜 MVC
    // 마치 브라우저에서 사용하는 것처럼 만들어서 Controller를 실행해볼 수 있습니다.
    private MockMvc mvc;

    // org.junit.Before
    // 적용된 메소드들을 모든 테스트 전에 한번씩 실행한다.
    @Before
    public void setup() {
        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }

    @Test
    public void joinTest() throws Exception {
        // perform 안에다가 어떤 요청을 만들어서 넘겨주면 mvc가 행동을 한다.
        // perform은 가상의 요청을 처리한다.
        // MockMvcRequestBuilders.get("/user/join") : /user/join get방식 요청을 보내는 자체
        // .andReturn() : 요청에 대한 결과 즉, 응답이다. 뷰나 모델을 포함하고 있다.
        ModelAndView mav = mvc.perform(MockMvcRequestBuilders.get("/user/join"))
                .andReturn()
                .getModelAndView();

        // 어떤 뷰를 찾아갈건지
        log.info(mav.getViewName());
        // 어떤 모델에 어떤 데이터들이 담겨있는지 확인할 수 있다.
        log.info(mav.getModelMap());
    }
}

여기서 joinTest() 테스트는 파라미터를 보내주는 것이 아니라 페이지 이동만 해주는 테스트다.

다시 UserController로 돌아가서 join을 해보고 sql을 select해보면 인코딩이 깨지는 문제를 확인할 수 있다.

  @PostMapping("/join")
    // 자연스럽게 날라온 응답객체를 addCookie로 보내주기 위해서 매개변수로 받는다.
    public String join(UserDTO user, HttpServletResponse resp) {
        if(service.join(user)) {
            Cookie joinId = new Cookie("joinId", user.getUserId());
            // 쿠키 종료
            // 쿠키 expiration 타임
            joinId.setMaxAge(300);
            // 쿠키 저장
            resp.addCookie(joinId);
        }
        // 그냥 return "이름"을 하면 이름에 해당하는 view를 보여주는 것이고
        // return "redirect:/"을 하면 redirect: 오른쪽 주소로 URL요청을 다시 하는 것입니다.
        // 그로 인해 주소가 바뀌고 해당 URL에 속하는 컨트롤러의 함수가 한번 더 호출이 되는 것이다.
        return "redirect:/";
    }

여기서 보면 UserDTO user 매개변수로 바로 들어오는데 그전에 listenerfilter을 들린다. web.xml가면 확인할 수 있다.

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

이게 listener인데 listener은 어떤 요청이 오던 이 listener은 무조건 작동을 한다.

filter은 특정 서블릿에 직접 달아줘야 한다. 우리가 지정해 놓은 서블릿의 경우 그 filter을 먼저 걸쳐라!

web.xml

<filter>
    <filter-name>encoding</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encoding</filter-name>
    <servlet-name>appServlet</servlet-name>
  </filter-mapping>

여기서 filte-mapping안에 servlet-name을 보면 appServlet이라고 해줬는데 이 의미는 appServlet을 가지전에 들리라는 것이다. appServlet은 DispatcherServlet인데 Spring은 항상 DispatcherServlet을 먼저 들린다. DispatcherServlet을 들려서 HandlerMapping을 통해 request의 처리를 담당하는 controller을 찾기 때문에 DispatcherServlet이 1순위이다. 그렇기 때문에 이렇게 설정을 해주면 filter을 통해서 인코딩 처리가 되는 것이다. DispatcherServlet전에 filter을 먼저 가기 때문이다.


위에서 작성한 controller을 테스트를 해보자!

UserControllerTest

 @Test
    public void loginTest() throws  Exception {
        ModelAndView mav = mvc.perform(MockMvcRequestBuilders.post("/user/login")
                .param("userId", "apple")
                .param("userPw", "zxzz12")
        ).andReturn()
                .getModelAndView();

        // 어떤 뷰를 찾아갈건지
        log.info(mav.getViewName());
        // 어떤 모델에 어떤 데이터들이 담겨있는지 확인할 수 있다.
        log.info(mav.getModelMap());
    }
  @Test
    public void joinTest2() throws Exception {
        // mvc.perform(요청) : 해당 요청대로 mockMVC 수행
        //                              요청제작자               post방식          /user/join으로 보내는 요청을 생성
        ModelAndView mav = mvc.perform(MockMvcRequestBuilders.post("/user/join")
                .param("userId", "bananasd")     // ← 요청을 파라미터로 담아서 요청 보내기
                .param("userPw", "zxzz12")
                .param("userName", "바나나")
        ).andReturn()       // 반환된 결과 : 응답(뷰, 모델 등을 포함)
                .getModelAndView(); // 응답에서 모델과 뷰를 포함하고 있는 타입의 객체 받기

        log.info(mav.getViewName());
        log.info(mav.getModelMap());
    }
   @Test
    public void logoutTest() throws Exception {
        ModelAndView mav = mvc.perform(MockMvcRequestBuilders.get("/user/logout"))
                .andReturn()
                .getModelAndView();

        log.info(mav.getViewName());
        log.info(mav.getModelMap());
    }

profile
발전하기 위한 공부

0개의 댓글