Junit Test Application-28-계좌등록 기능

jaegeunsong97·2023년 8월 6일
0

Junit Bank Application 깃허브

Junit Bank Application 기록 노션

계좌등록 서비스 코드

package shop.mtcoding.bank.service;

import java.util.Optional;

import javax.validation.constraints.Digits;
import javax.validation.constraints.NotNull;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import shop.mtcoding.bank.domain.account.Account;
import shop.mtcoding.bank.domain.account.AccountRepository;
import shop.mtcoding.bank.domain.user.User;
import shop.mtcoding.bank.domain.user.UserRepository;
import shop.mtcoding.bank.handler.ex.CustomApiException;

@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class AccountService {

     private final UserRepository userRepository;
     private final AccountRepository accountRepository;

     @Transactional
     public AccountSaveResponseDto 계좌등록(AccountSaveRequestDto accountSaveRequestDto, Long userId) {
          // 1. User DB 검증
          User userPS = userRepository.findById(userId).orElseThrow(
                    () -> new CustomApiException("유저를 찾을 수 없습니다. "));

          // 2. 계좌 DB 중복 여부 검증
          Optional<Account> accountOP = accountRepository.findByNumber(accountSaveRequestDto.getNumber());
          if (accountOP.isPresent()) {
               throw new CustomApiException("해당 계좌가 이미 존재합니다. ");
          }

          // 3. 계좌 등록
          Account accountPS = accountRepository.save(accountSaveRequestDto.toEntity(userPS));

          // 4. DTO
          return new AccountSaveResponseDto(accountPS);
     }

     @Getter
     @Setter
     public static class AccountSaveResponseDto {

          private Long id;
          private Long number;
          private Long balance;

          public AccountSaveResponseDto(Account account) {
               this.id = account.getId();
               this.number = account.getNumber();
               this.balance = account.getBalance();
          }
     }

     @Getter
     @Setter
     public static class AccountSaveRequestDto {

          @NotNull
          @Digits(integer = 4, fraction = 4)
          private Long number;
          @NotNull
          @Digits(integer = 4, fraction = 4)
          private Long password;

          public Account toEntity(User user) {
               return Account.builder()
                         .number(number)
                         .password(password)
                         .balance(1000L)
                         .user(user)
                         .build();
          }
     }
}

이제 컨트롤러 코드를 만들어보자

package shop.mtcoding.bank.web;

import javax.validation.Valid;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import lombok.RequiredArgsConstructor;
import shop.mtcoding.bank.config.auth.LoginUser;
import shop.mtcoding.bank.dto.ResponseDto;
import shop.mtcoding.bank.dto.account.AccountRequestDto.AccountSaveRequestDto;
import shop.mtcoding.bank.dto.account.AccountResponseDto.AccountSaveResponseDto;
import shop.mtcoding.bank.service.AccountService;

@RequiredArgsConstructor
@RequestMapping("/api")
@RestController
public class AccountController {

     private final AccountService accountService;

     @PostMapping("/")
     public ResponseEntity<?> saveAccount(@RequestBody @Valid AccountSaveRequestDto accountSaveRequestDto,
               BindingResult bindingResult,
               @AuthenticationPrincipal LoginUser loginUser) {
          AccountSaveResponseDto accountSaveResponseDto = accountService.계좌등록(accountSaveRequestDto,
                    loginUser.getUser().getId());
          return new ResponseEntity<>(new ResponseDto<>(1, "계좌등록 성공", accountSaveResponseDto), HttpStatus.CREATED);
     }
}

LoginUser 에는 id, role 만 존재 : JwtAuthorizationFilter 확인

DTO의 경우는 dto로 옮기기

package shop.mtcoding.bank.dto.account;

import javax.validation.constraints.Digits;
import javax.validation.constraints.NotNull;

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

public class AccountRequestDto {

     @Getter
     @Setter
     public static class AccountSaveRequestDto {

          @NotNull
          @Digits(integer = 4, fraction = 4)
          private Long number;
          @NotNull
          @Digits(integer = 4, fraction = 4)
          private Long password;

          public Account toEntity(User user) {
               return Account.builder()
                         .number(number)
                         .password(password)
                         .balance(1000L)
                         .user(user)
                         .build();
          }
     }
}
package shop.mtcoding.bank.dto.account;

import lombok.Getter;
import lombok.Setter;
import shop.mtcoding.bank.domain.account.Account;

public class AccountResponseDto {

     @Getter
     @Setter
     public static class AccountSaveResponseDto {

          private Long id;
          private Long number;
          private Long balance;

          public AccountSaveResponseDto(Account account) {
               this.id = account.getId();
               this.number = account.getNumber();
               this.balance = account.getBalance();
          }
     }
}

이거를 POST맨으로 하려면 회원가입 로그인 까지 항상 해야하기 때문에 너무 귀찮다. 따라서 더미 데이터를 넣어준다.

package shop.mtcoding.bank.config.dummy;

import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

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

@Configuration
public class DummyDevInit extends DummyObject {

     @Profile("dev") // dev만 동작, prod는 실행 안되야함
     @Bean
     CommandLineRunner init(UserRepository userRepository) {
          return (args) -> {
               // 서버 실행 시, 무조건 실행
               User ssar = userRepository.save(newUser("ssar", "쌀"));
          };
     }
}

dev를 TRACE로 해서 내용을 볼 수 있다.

insert 쿼리 1개

회원가입 필요없이 로그인이 바로가능하다

베리어 토큰과 같이 보내면

쿼리를 보면

서비스단에서 user 찾는 부분

계좌 찾는 부분

계좌 insert

주목할 점


Account를 가보면 user와 LAZY상태로 되어있다. 따라서 알수 있듯이 user 데이터를 가져오지 않는다. 만약 account.getUser().아무 필드 를 하는 순간 User가 LAZY하게 발동이 된다.

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

0개의 댓글