728x90
1. test 목적
- @transactional test를 할 때, spring container를 이용한 proxy 객체 생성을 해야해서 일반 java 단위 test로 검사가 불가하다.
- 때문에 test code 내부에 bean 등록과 spring container 환경, DI 를 이용해서 test 수행
package hello.jdbc.service;
import static hello.jdbc.connection.ConnectionConst.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@Slf4j
@SpringBootTest // spring이 springContainer를 띄운다. - @Transactional 사용시, proxy에서 @bean을 사용하기 때문
class MemberServiceV3_3Test {
@Autowired
private MemberRepositoryV3 memberRepository;
@Autowired
private MemberServiceV3_3 memberService;
// 이전 의존관계 주입을 하려는 memberRepository, memberService를 bean으로 등록해야 DI 가 가능해짐
@TestConfiguration // testCode 내부에서 bean 등록하는 방법
static class TestConfig{
@Bean
DataSource dataSource() { return new DriverManagerDataSource(URL,USERNAME,PASSWORD); }
// transactionManger는 proxy(@Transactional)로부터 내부적으로 사용해야하기 때문에 bean 등록
@Bean
PlatformTransactionManager transactionManager(){
return new DataSourceTransactionManager(dataSource());
}
@Bean
MemberRepositoryV3 memberRepositoryV3() {
return new MemberRepositoryV3(dataSource());
}
@Bean
MemberServiceV3_3 memberServiceV3_3() {
return new MemberServiceV3_3(memberRepositoryV3());
}
}
/* *
@BeforeEach
void before(){
// 설정으로 관리한 것
DriverManagerDataSource dataSource = new DriverManagerDataSource(URL, USERNAME, PASSWORD);
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
memberRepository = new MemberRepositoryV3(dataSource);
memberService = new MemberServiceV3_3(memberRepository); // transaction 사용 위해서 dataSource 넘김
}
*/
@AfterEach
void after() throws SQLException {
memberRepository.delete("memberA");
memberRepository.delete("memberB");
memberRepository.delete("ex");
}
@Test
void accountTransfer() throws SQLException {
//given
Member memberA = new Member("memberA", 10000);
Member memberB = new Member("memberB", 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);
}
@Test
void accountTransferEx() throws SQLException {
//given
Member memberA = new Member("memberA", 10000);
Member memberEx = new Member("ex", 10000);
memberRepository.save(memberA);
memberRepository.save(memberEx);
//when
// accountTransfer으 실제 내부적의 business logic인 bizLogic()에서 params를 4개를 받지만
// accountTransfer은 3개의 params만 받으면 된다.
assertThatThrownBy(()->memberService.accountTransfer(memberA.getMemberId(), memberEx.getMemberId(), 2000))
.isInstanceOf(IllegalStateException.class);
//then
Member findMemberA = memberRepository.findById(memberA.getMemberId());
Member findMemberEx = memberRepository.findById(memberEx.getMemberId());
assertThat(findMemberA.getMoney()).isEqualTo(10000);
assertThat(findMemberEx.getMoney()).isEqualTo(10000);
}
// proxy 적용 확인 test
@Test
void AopCheck() {
log.info("memberService class={}", memberService.getClass());
log.info("memberRepository class={}", memberRepository.getClass());
Assertions.assertThat(AopUtils.isAopProxy(memberService)).isTrue();
Assertions.assertThat(AopUtils.isAopProxy(memberRepository)).isFalse();
}
}
- @SpringBootTest : springboot 환경 설정 - springboot가 제공하는 기본 @bean은 자동 등록
- @TestConfiguration: test 환경 내부에서 사용자 @Bean 등록방법
참고 발행글 : 2023.09.23 - [spring/spring db1] - 4. 스프링과 문제해결 - 트랜잭션