728x90
이전글
목표
- 1. controller / 2. service로 나눠서 테스트를 진행해야 함.
- 1. 성공, 2. 실패 테스트 케이스를 모두 통과하는 실제 코드 작성.
- Exception 처리는 enum Error코드에 작성 후 호출 해서 사용
- 실패의 경우 enum값의 errorCode로 처리하기
- when(어떤 상황일 때)를 각각 설계해 보고, Test case에 따라 예상되는 결괏값을 작성해 주기
- Controller, Service 두 클래스의 테스트 코드 작성하기
체크사항
회원가입
controller
- 회원가입 성공
- 회원가입 실패 - userName 중복(이미 가입된 회원이 있는 경우)
로그인
controller
- 로그인 성공
- 로그인 실패 - userName 없음(가입이 되어있지 않은 경우)
- 로그인 실패 - password 오류.
User Controller Test
basic
@WebMvcTest(UserController.class)
@WithMockUser
class UserControllerTest {
@Autowired
MockMvc mockMvc;
@Autowired
ObjectMapper objectMapper;
@MockBean
UserService userService;
private String token;
@Value("${jwt.secret}")
private String secretKey;
@BeforeEach()
public void getToken() {
long expireTimeMs = 1000 * 60 * 60;
token = JwtUtil.createJwt("chordpli", secretKey, System.currentTimeMillis() + expireTimeMs);
}
}
- @SpringBootTest가 아닌, @WebMvcTest를 사용하였습니다.
- @SpringBootTest를 사용하면 스프링이 구동되면서 모든 빈을 로드하기 때문에 시간이 오래 걸리고, 단위가 커져서 세부적인 테스트를 하기 어려워지기 때문입니다.
- @WithMockUser 어노테이션을 사용해서 Spring Security 인증을 받아옵니다.
- @Autowired를 사용해서 의존성을 주입합니다.
- MockMvc, ObjectMapper의 의존성을 주입합니다.
- @MockBean을 사용해서 UserService를 선언합니다.
- token을 발급하는 상황을 가정하기 위해 secretKey, token, getToken()을 만들고 선언하였습니다.
회원가입 Test
회원가입 성공
...
class UserControllerTest {
...
/* 회원가입 */
@Test
@DisplayName("회원가입 성공")
void join_success() throws Exception {
UserDto userDto = UserDto.builder()
.id(1)
.userName("jun")
.password("abcd")
.userRole(UserRole.USER)
.build();
UserJoinRequest request = new UserJoinRequest("jun", "abcd");
given(userService.join(any()))
.willReturn(userDto);
String url = "/api/v1/users/join";
mockMvc.perform(post(url).with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(request)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.resultCode").exists())
.andExpect(jsonPath("$.resultCode").value("SUCCESS"))
.andExpect(jsonPath("$.result.userId").exists())
.andExpect(jsonPath("$.result.userId").value(1))
.andExpect(jsonPath("$.result.userName").exists())
.andExpect(jsonPath("$.result.userName").value("jun"))
.andDo(print());
verify(userService, times(1)).join(any());
}
}
- 회원가입 후 생성되는 UserDto를 생성합니다.
- 회원가입할 때 필요한 정보를 받을 UserJoinRequest를 생성합니다.
- userService.join을 했을 때, userDto를 반환받습니다.
- post형식으로 url에 요청을 보내고 그 요청에는 request가 담겨 있습니다.
- given 했을 때 우리는 userDto를 받기로 했기 때문에 userDto의 내용들이 잘 담겨있는지 andExpect를 사용해서 값들이 존재하는지, 값이 일치하는지 확인합니다.
- verify를 사용해서 userService의 join이 몇 번 사용됐는지 확인합니다.
회원가입 실패
...
class UserControllerTest {
...
/* 회원가입 */
@Test
@DisplayName("회원가입 실패 - userName 중복")
void join_fail() throws Exception {
UserJoinRequest request = new UserJoinRequest("jun", "abcd");
given(userService.join(any()))
.willThrow(new SNSAppException(DUPLICATED_USER_NAME, DUPLICATED_USER_NAME.getMessage()));
String url = "/api/v1/users/join";
mockMvc.perform(post(url).with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(request)))
.andExpect(status().isConflict())
.andDo(print());
}
}
- 회원가입할 때 필요한 정보를 받을 UserJoinRequest를 생성합니다.
- userService.join을 실행했을 때 DUPLICATED_USER_NAME예외를 던집니다.
- post형식으로 url에 요청을 보내고 그 요청에는 request가 담겨 있습니다.
- http status가 confilct가 맞는지 확인합니다.
로그인 테스트
로그인 성공
...
class UserControllerTest {
...
/* 로그인 */
@Test
@DisplayName("로그인 성공")
void login_success() throws Exception {
UserDto userDto = UserDto.builder()
.id(1)
.userName("jun")
.password("abcd")
.userRole(UserRole.USER)
.build();
UserLoginRequest request = new UserLoginRequest(userDto.getUserName(), userDto.getPassword());
UserLoginResponse response = new UserLoginResponse(token);
given(userService.login(any())).willReturn(response);
String url = "/api/v1/users/login";
mockMvc.perform(post(url).with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(request)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.resultCode").exists())
.andExpect(jsonPath("$.resultCode").value("SUCCESS"))
.andExpect(jsonPath("$.result.jwt").exists())
.andExpect(jsonPath("$.result.jwt").value(token))
.andDo(print());
verify(userService, times(1)).login(any());
}
}
- UserDto를 만들고, Login 할 때 필요한 정보를 UserDto에서 가져옵니다.
- UserLoginResponse를 만들고 token 정보를 입력합니다.
- userService가 login을 사용할 때 token을 가지고 있는 UserLoginResponse가 반환되도록 합니다.
- post형식의 login url을 호출했을 때 request를 넘기고, 그에 따른 결과 값이 존재하는지, 원하는 값과 동일한지 확인합니다.
로그인 실패 - 사용자가 존재하지 않을 때
...
class UserControllerTest {
...
/* 로그인 */
...
@Test
@DisplayName("로그인 실패_userName 없음")
void login_fail_empty_user_name() throws Exception {
UserDto userDto = UserDto.builder()
.id(1)
.userName("jun")
.password("abcd")
.userRole(UserRole.USER)
.build();
UserLoginRequest request = new UserLoginRequest("abc", "bbcd");
given(userService.login(any()))
.willThrow(new SNSAppException(USERNAME_NOT_FOUND, USERNAME_NOT_FOUND.getMessage()));
String url = "/api/v1/users/login";
mockMvc.perform(post(url).with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(request)))
.andExpect(status().isNotFound())
.andDo(print());
}
}
- "abc"라는 userName을 가지고 있는 User가 없다고 가정합니다.
- userSerivce의 login을 사용했을 때, USERNAME_NOT_FOUND예외를 던져줍니다.
- post형식의 login url을 호출했을 때 request를 넘기고, 그에 따른 http status가 NotFound가 나왔는지 확인합니다.
로그인 실패 - password 불일치
...
class UserControllerTest {
...
/* 로그인 */
@Test
@DisplayName("로그인 실패_password 오류")
void login_fail_wrong_password() throws Exception {
UserDto userDto = UserDto.builder()
.id(1)
.userName("jun")
.password("abcd")
.userRole(UserRole.USER)
.build();
UserLoginRequest dto = new UserLoginRequest(userDto.getUserName(), "bbcd");
given(userService.login(any()))
.willThrow(new SNSAppException(INVALID_PASSWORD, INVALID_PASSWORD.getMessage()));
String url = "/api/v1/users/login";
mockMvc.perform(post(url).with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(dto)))
.andExpect(status().isUnauthorized())
.andDo(print());
}
}
- "jun"라는 userName을 가지고 있는 User의 비밀번호는 "abcd"입니다.
- 로그인하려는 dto의 비밀번호는 "bbcd"입니다.
- userSerivce의 login을 사용했을 때, INVALID_PASSWORD 예외를 던져줍니다.
- post형식의 login url을 호출했을 때 request를 넘기고, 그에 따른 http status가 isUnauthorized가 나왔는지 확인합니다.
다음글
반응형
'프로젝트 > Archive' 카테고리의 다른 글
[04] Post Test 코드 작성 - 2 (Service Test) (0) | 2022.12.27 |
---|---|
[04] Post Test 코드 작성 - 1 (Controller Test) (0) | 2022.12.27 |
[JWT] JWT Exception 처리 (0) | 2022.12.25 |
[03] 게시된 포스트 삭제 (0) | 2022.12.23 |
[03] 게시된 포스트 수정 (0) | 2022.12.23 |