지금까지 배운 트랜잭션 개념을 애플리케이션에서 코드로 실습해보자.
계좌이체 예제를 만들어볼 것임. 서비스단부터 만들어보자.
@RequiredArgsConstructor
public class MemberServiceV1 {
private final MemberRepositoryV1 memberRepository;
public void accountTransfer(String fromId, String toId, int money) throws SQLException {
Member fromMember = memberRepository.findById(fromId);
Member toMember = memberRepository.findById(toId);
memberRepository.update(fromId, fromMember.getMoney() - money);
//오류 케이스
if(toMember.getMemberId().equals("ex")) {
throw new IllegalStateException(("계좌이체중 문제발생"));
}
memberRepository.update(toId, toMember.getMoney() + money);
}
}
계좌이체를 하는 동안 예외상황을 만들어보기 위해 중간에 if문을 넣었다.
먼저 정상적인 상황을 테스트해보자.
package hello.jdbc.service;
import hello.jdbc.domain.Member;
import hello.jdbc.repository.MemberRepositoryV1;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import java.sql.SQLException;
import static hello.jdbc.connection.ConnectionConst.*;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* 기본동작, 트랜잭션이 없이 중간에 문제가 발생한다.
*/
class MemberServiceV1Test {
public static final String MEMBER_A = "memberA";
public static final String MEMBER_B = "memberB";
public static final String MEMBER_EX = "ex";
private MemberRepositoryV1 memberRepository;
private MemberServiceV1 memberService;
@BeforeEach
void before() {
DriverManagerDataSource dataSource = new DriverManagerDataSource(URL, USERNAME, PASSWORD);
memberRepository = new MemberRepositoryV1(dataSource);
memberService = new MemberServiceV1(memberRepository);
}
@AfterEach
void after() throws SQLException {
memberRepository.delete(MEMBER_A);
memberRepository.delete(MEMBER_B);
memberRepository.delete(MEMBER_EX);
}
@DisplayName("정상 이체")
@Test
public void accountTransfer () throws SQLException {
//given
Member memberA = new Member(MEMBER_A, 10000);
Member memberB = new Member(MEMBER_B, 10000);
memberRepository.save(memberA);
memberRepository.save(memberB);
// when
//계좌이체 진행
memberService.accountTransfer(memberA.getMemberId(), memberB.getMemberId(), 2000);
// then
Member findmemberA = memberRepository.findById(memberA.getMemberId());
Member findmemberB = memberRepository.findById(memberB.getMemberId());
assertThat(findmemberA.getMoney()).isEqualTo(8000);
assertThat(findmemberB.getMoney()).isEqualTo(12000);
}
}
문제가없으므로, A의 돈 2000원이 줄고, B의 돈은 2000이 늘어나야 한다.
테스트 성공했다.
이제 이체중에 예외가 발생하는 케이스이다.
memberB를 문제의 EX로 바꿔주자.
이제 예외가 터져야 한다. 예외터지는걸 검증해야 하므로