서비스 코드에 있는 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");
}
}