Junit Test Application-12-회원가입 서비스 리펙토링

jaegeunsong97·2023년 8월 4일
0

Junit Bank Application 깃허브

Junit Bank Application 기록 노션

서비스 코드에 있는 DTO 옮기기

package shop.mtcoding.bank.service;

import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;
import shop.mtcoding.bank.domain.user.User;
import shop.mtcoding.bank.domain.user.UserRepository;
import shop.mtcoding.bank.dto.user.UserRequestDto.JoinRequestDto;
import shop.mtcoding.bank.dto.user.UserResponseDto.JoinResponseDto;
import shop.mtcoding.bank.handler.ex.CustomApiException;

@RequiredArgsConstructor
@Service
public class UserService {

     private final Logger log = LoggerFactory.getLogger(getClass());
     private final UserRepository userRepository;
     private final BCryptPasswordEncoder passwordEncoder;

     @Transactional
     public JoinResponseDto 회원가입(JoinRequestDto joinRequestDto) {
          // 1. 동일 유저네임 검사
          Optional<User> userOP = userRepository.findByUsername(joinRequestDto.getUsername());
          if (userOP.isPresent()) {
               throw new CustomApiException("동일한 유저네임이 존재합니다. ");
          }

          // 2. 패스워드 인코딩 + 회원가입
          User userPS = userRepository.save(joinRequestDto.toEntity(passwordEncoder));

          // 3. dto 응답
          return new JoinResponseDto(userPS);
     }
}

userDTO 2개 생성

package shop.mtcoding.bank.dto.user;

import lombok.Getter;
import lombok.Setter;
import shop.mtcoding.bank.domain.user.User;

public class UserResponseDto {

     @Getter
     @Setter
     public static class JoinResponseDto {

          private Long id;
          private String username;
          private String fullname;

          public JoinResponseDto(User user) {
               this.id = user.getId();
               this.username = user.getUsername();
               this.fullname = user.getFullname();
          }
     }
}
package shop.mtcoding.bank.dto.user;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import lombok.Getter;
import lombok.Setter;
import shop.mtcoding.bank.domain.user.User;
import shop.mtcoding.bank.domain.user.UserEnum;

public class UserRequestDto {

     @Getter
     @Setter
     public static class JoinRequestDto {
          // 유효성 검사
          private String username;
          private String password;
          private String email;
          private String fullname;

          public User toEntity(BCryptPasswordEncoder passwordEncoder) {
               return User.builder()
                         .username(username)
                         .password(passwordEncoder.encode(password))
                         .email(email)
                         .fullname(fullname)
                         .role(UserEnum.CUSTOMER)
                         .build();
          }
     }
}

테스트 할때마다 stub 부분에 User를 빌더로 작성하는 거 불편 따라서 Dummy를 만들기

package shop.mtcoding.bank.config.dummy;

import java.time.LocalDateTime;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import shop.mtcoding.bank.domain.user.User;
import shop.mtcoding.bank.domain.user.UserEnum;

public class DummyObject {

     protected User newUser(String username, String fullname) {
          BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
          String encPassword = passwordEncoder.encode("1234");
          return User.builder()
                    .username(username)
                    .password(encPassword)
                    .email(username + "@nate.com")
                    .fullname(fullname)
                    .role(UserEnum.CUSTOMER)
                    .build();
     }

     protected User newMockUser(Long id, String username, String fullname) {
          BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
          String encPassword = passwordEncoder.encode("1234");
          return User.builder()
                    .id(id)
                    .username(username)
                    .password(encPassword)
                    .email(username + "@nate.com")
                    .fullname(fullname)
                    .role(UserEnum.CUSTOMER)
                    .createAt(LocalDateTime.now())
                    .updateAt(LocalDateTime.now())
                    .build();
     }
}

newUser는 진짜로 DB에 들어가는 것이기 때문에 id, 2개 날짜 필요없음
하지만 newMockUser는 오직 테스트용이고 가짜환경에서 만들어지기 떄문에 모든 정보들이 필요

package shop.mtcoding.bank.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

import java.util.Optional;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import shop.mtcoding.bank.config.dummy.DummyObject;
import shop.mtcoding.bank.domain.user.User;
import shop.mtcoding.bank.domain.user.UserRepository;
import shop.mtcoding.bank.dto.user.UserRequestDto.JoinRequestDto;
import shop.mtcoding.bank.dto.user.UserResponseDto.JoinResponseDto;

@ExtendWith(MockitoExtension.class)
public class UserServiceTest extends DummyObject {

     @InjectMocks // 가짜환경에 넣는 것, @Autowired랑 다름
     private UserService userService;
     @Mock
     private UserRepository userRepository;
     @Spy
     private BCryptPasswordEncoder bCryptPasswordEncoder;

     @Test
     public void 회원가입_test() throws Exception {
          // given
          JoinRequestDto joinRequestDto = new JoinRequestDto();
          joinRequestDto.setUsername("ssar");
          joinRequestDto.setPassword("1234");
          joinRequestDto.setEmail("ssar@nate.com");
          joinRequestDto.setFullname("쌀");

          // stub 1
          when(userRepository.findByUsername(any())).thenReturn(Optional.empty());

          // stub 2
          User ssar = newMockUser(1L, "ssar", "쌀");
          when(userRepository.save(any())).thenReturn(ssar);

          // when
          JoinResponseDto joinResponseDto = userService.회원가입(joinRequestDto);

          // then
          assertThat(joinResponseDto.getId()).isEqualTo(1L);
          assertThat(joinResponseDto.getUsername()).isEqualTo("ssar");
     }
}

profile
블로그 이전 : https://medium.com/@jaegeunsong97

0개의 댓글