레포지토리 테스트를 할 것이기 때문에 해당 부분만 띄우면 된다. @SpringBootTest를 띄워서 전체를 Mock에 할 필요가 없는 것.
결론 : @DataJpaTest -> DB와 관련된 Bean이 전부 등록
TransactionRepository는 JpaRepository<>와 Dao를 extend 하고 있다. 그리고 Dao를 TransactionRepositoryImpl이 가지고 있다.
따라서 TransactionRepository를 TransactionRepositoryImpl 동일하게 봐도 된다.
package shop.mtcoding.bank.domian.trasaction;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import shop.mtcoding.bank.config.dummy.DummyObject;
import shop.mtcoding.bank.domain.account.Account;
import shop.mtcoding.bank.domain.account.AccountRepository;
import shop.mtcoding.bank.domain.transaction.Transaction;
import shop.mtcoding.bank.domain.transaction.TransactionRepository;
import shop.mtcoding.bank.domain.user.User;
import shop.mtcoding.bank.domain.user.UserRepository;
@DataJpaTest
public class TransactionRepositoryImpl extends DummyObject {
@Autowired
private UserRepository userRepository;
@Autowired
private AccountRepository accountRepository;
@Autowired
private TransactionRepository transactionRepository;
@BeforeEach
public void setUp() {
dataSetting();
}
private void dataSetting() {
User ssar = userRepository.save(newUser("ssar", "쌀"));
User cos = userRepository.save(newUser("cos", "코스,"));
User love = userRepository.save(newUser("love", "러브"));
User admin = userRepository.save(newUser("admin", "관리자"));
Account ssarAccount1 = accountRepository.save(newAccount(1111L, ssar));
Account cosAccount = accountRepository.save(newAccount(2222L, cos));
Account loveAccount = accountRepository.save(newAccount(3333L, love));
Account ssarAccount2 = accountRepository.save(newAccount(4444L, ssar));
Transaction withdrawTransaction1 = transactionRepository
.save(newWithdrawTransaction(ssarAccount1, accountRepository));
Transaction depositTransaction1 = transactionRepository
.save(newDepositTransaction(cosAccount, accountRepository));
Transaction transferTransaction1 = transactionRepository
.save(newTransferTransaction(ssarAccount1, cosAccount, accountRepository));
Transaction transferTransaction2 = transactionRepository
.save(newTransferTransaction(ssarAccount1, loveAccount, accountRepository));
Transaction transferTransaction3 = transactionRepository
.save(newTransferTransaction(cosAccount, ssarAccount1, accountRepository));
}
}
public class DummyObject {
protected Transaction newWithdrawTransaction(Account account, AccountRepository accountRepository) {
account.withdraw(100L); // 1000원이 있었다면 900원이 됨
// Repository Test에서는 더티체킹 됨
// Controller Test에서는 더티체킹 안됨
if (accountRepository != null) {
accountRepository.save(account);
}
Transaction transaction = Transaction.builder()
.withdrawAccount(account)
.depositAccount(null)
.withdrawAccountBalance(account.getBalance())
.depositAccountBalance(null)
.amount(100L)
.gubun(TransactionEnum.WITHDRAW)
.sender(account.getNumber() + "")
.receiver("ATM")
.build();
return transaction;
}
protected Transaction newDepositTransaction(Account account, AccountRepository accountRepository) {
account.deposit(100L); // 1000원이 있었다면 900원이 됨
// 더티체킹이 안되기 때문에
if (accountRepository != null) {
accountRepository.save(account);
}
Transaction transaction = Transaction.builder()
.withdrawAccount(null)
.depositAccount(account)
.withdrawAccountBalance(null)
.depositAccountBalance(account.getBalance())
.amount(100L)
.gubun(TransactionEnum.DEPOSIT)
.sender("ATM")
.receiver(account.getNumber() + "")
.tel("01022227777")
.build();
return transaction;
}
protected Transaction newTransferTransaction(Account withdrawAccount, Account depositAccount,
AccountRepository accountRepository) {
withdrawAccount.withdraw(100L);
depositAccount.deposit(100L);
// 더티체킹이 안되기 때문에
if (accountRepository != null) {
accountRepository.save(withdrawAccount);
accountRepository.save(depositAccount);
}
Transaction transaction = Transaction.builder()
.withdrawAccount(withdrawAccount)
.depositAccount(depositAccount)
.withdrawAccountBalance(withdrawAccount.getBalance())
.depositAccountBalance(depositAccount.getBalance())
.amount(100L)
.gubun(TransactionEnum.TRANSFER)
.sender(withdrawAccount.getNumber() + "")
.receiver(depositAccount.getNumber() + "")
.build();
return transaction;
}
서비스 레이어에서 체크한 것이 아니기 때문에 더티 체킹이 되지 않는다. 그래서 필요한 코드가
이렇게 변경이 되면 DB에 저장을 해줘야한다.