개발자의 서재

Chaptor.08 - 단위 테스트 코드 작성(Controller별 테스트) 본문

SpringBootProject/SringBoot_JWT_RestApi

Chaptor.08 - 단위 테스트 코드 작성(Controller별 테스트)

ironmask431 2022. 4. 18. 22:34

각 Controller 의 mapping Url 별 테스트코드를 작성해보았다. 

@SpringBootTest 를 사용하였고, 

@Before 에서는 data.sql을 통해 insert 되는 기본 데이터를 삭제하고 

테스트용 user 정보입력 + Security Context 에 user 정보를 등록하고,  jwt 토큰 발급 + 헤더에 토큰등록을 

하여 토큰인증이 필요한 api가 정상 실행되도록 하였다. 

 

@After 에서는 

테스트 후 입력된 데이터를 모두 삭제하도록 하였다. 

 

JoinControllerTest.java

package com.leesh.springbootjwttutorial.restApiTest;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.leesh.springbootjwttutorial.dto.UserDto;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.hamcrest.Matchers.is;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class JoinControllerTest {

    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ProductConterllerTest.class);

    @LocalServerPort
    private int port;

    @Autowired
    private WebApplicationContext context;

    private MockMvc mvc;

    //테스트용 유저 데이터
    private String email = "test@gmail.com";
    private String password = "test";

    @Before //테스트 시작전 실행
    public void setUp(){
        mvc = MockMvcBuilders
                .webAppContextSetup(context)
                .apply(springSecurity()).build();
    }

    @After // 테스트 후 실행
    public void tearDown() throws Exception {

    }

    @Test
    public void 회원가입() throws Exception {
        //given
        String url = "http://localhost:"+port+"/api/join/signup";

        UserDto userDto = new UserDto();
        userDto.setEmail(email);
        userDto.setPassword(password);

        log.info("userDto.getEmail()="+userDto.getEmail());
        log.info("userDto.getPassword()="+userDto.getPassword());

        //정상응답, 가입한 email과 "USER" 권한이 리턴되는지 확인
        mvc.perform(post(url)
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(new ObjectMapper().writeValueAsString(userDto)))
                        .andExpect(status().isOk())
                        .andExpect(jsonPath("$.email",is(email)))
                        .andExpect(jsonPath("$.authorities[0].authorityName",is("ROLE_USER")))
        ;
    }
}

 

AuthControllerTest.java

package com.leesh.springbootjwttutorial.restApiTest;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.leesh.springbootjwttutorial.dto.UserDto;
import com.leesh.springbootjwttutorial.entity.Authority;
import com.leesh.springbootjwttutorial.entity.User;
import com.leesh.springbootjwttutorial.jwt.JwtFilter;
import com.leesh.springbootjwttutorial.jwt.TokenProvider;
import com.leesh.springbootjwttutorial.repository.UserRepository;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import java.util.Collections;

import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class AuthControllerTest {

    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ProductConterllerTest.class);

    @LocalServerPort
    private int port;

    @Autowired
    private WebApplicationContext context;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private TokenProvider tokenProvider;
    @Autowired
    private AuthenticationManagerBuilder authenticationManagerBuilder;
    @Autowired
    private PasswordEncoder passwordEncoder;

    private MockMvc mvc;

    //테스트용 유저 데이터
    private Long userId;
    private String email = "test@gmail.com";
    private String password = "test";

    @Before //테스트 시작전 실행
    public void setUp(){
        mvc = MockMvcBuilders
                .webAppContextSetup(context)
                .apply(springSecurity()).build();

        //data.sql로 미리들어간 데이터가 있으므로 테스트 실행전 전체 삭제해줌.
        userRepository.deleteAll();

        //테스트용 유저정보 입력
        Authority authority = Authority.builder()
                .authorityName("ROLE_USER")
                .build();

        User user = User.builder()
                .email(email)
                .password(passwordEncoder.encode(password))
                .authorities(Collections.singleton(authority))
                .activated(true)
                .build();

        userRepository.save(user);

        //Security Context에 유저정보 등록, 토큰발급
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(email, password);

        Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
        SecurityContextHolder.getContext().setAuthentication(authentication);

        String jwt = tokenProvider.createToken(authentication);

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add(JwtFilter.AUTHORIZATION_HEADER,"Bearer "+ jwt);//
    }

    @After // 테스트 후 실행
    public void tearDown() throws Exception {
        userRepository.deleteAll();
    }

    @Test
    public void 로그인() throws Exception {
        //given
        String url = "http://localhost:"+port+"/api/auth/login";

        UserDto userDto = new UserDto();
        userDto.setEmail(email);
        userDto.setPassword(password);

        log.info("userDto.getEmail()="+userDto.getEmail());
        log.info("userDto.getPassword()="+userDto.getPassword());

        //정상응답, 토큰값이 리턴되었는지 확인
        mvc.perform(post(url)
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(new ObjectMapper().writeValueAsString(userDto)))
                        .andExpect(status().isOk())
                        .andExpect(jsonPath("$.token").exists())
        ;
    }
}

 

 

테스트 코드 작성후 실행시 아래 에러 발생 

https://ddasi-live.tistory.com/35 참고해서 수정함. 

 

JoinControllerTest.java 에서 

회원가입시 userDto 의 password가 null로 인식되어 계속 실패.. 
UserDto의 password 변수에 @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
를 주석처리하니 정상 동작.

 

전체 테스트 정상 확인 

Comments