Spring Data Jpa에서 flush()는 어떻게 하나요?
1618
작성한 질문수 2
일단 저의 전체 코드입니다.
package com.readingbooks.web.service.member;
import com.readingbooks.web.domain.enums.Gender;
import com.readingbooks.web.exception.member.MemberPresentException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@SpringBootTest
@Transactional
class MemberServiceTest {
@Autowired
private MemberService memberService;
@Test
void register_fail_null(){
RegisterRequest request = createRequest(null, null, null, null, null, null);
assertThatThrownBy(
()-> memberService.register(request))
.isInstanceOf(IllegalArgumentException.class);
}
@Test
void register_fail_invalid_email(){
RegisterRequest request = createRequest("tes@example.com", "test1234", "test", "1999", "01012341234", Gender.SECRET);
assertThatThrownBy(()->memberService.register(request))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("이메일을 올바르게 입력해주세요.");
}
@Test
void register_fail_invalid_short_password(){
RegisterRequest request = createRequest("test@example.com", "test", "test", "1999", "01012341234", Gender.SECRET);
assertThatThrownBy(()->memberService.register(request))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("비밀번호를 올바르게 입력해주세요. 비밀번호는 8-16자에 특수문자 '@, $, !, %, *, #, ?, &'가 포함되야 합니다.");
}
@Test
void register_fail_invalid_not_contained_password(){
RegisterRequest request = createRequest("test@example.com", "test", "test1234", "1999", "01012341234", Gender.SECRET);
assertThatThrownBy(()->memberService.register(request))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("비밀번호를 올바르게 입력해주세요. 비밀번호는 8-16자에 특수문자 '@, $, !, %, *, #, ?, &'가 포함되야 합니다.");
}
@Test
void register_fail_invalid_name(){
RegisterRequest request = createRequest("test@example.com", "test1234", "t", "1999", "01012341234", Gender.SECRET);
assertThatThrownBy(()->memberService.register(request))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("이름을 올바르게 입력해주세요.");
}
@Test
void register_fail_invalid_birthYear(){
RegisterRequest request = createRequest("test@example.com", "test1234!", "test", "19990115", "01012341234", Gender.SECRET);
assertThatThrownBy(()->memberService.register(request))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("생년을 올바르게 입력해주세요.");
}
@Test
void register_fail_invalid_phoneNo(){
RegisterRequest request = createRequest("test@example.com", "test1234!", "test", "1999", "0101234", Gender.SECRET);
assertThatThrownBy(()->memberService.register(request))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("핸드폰 번호를 올바르게 입력해주세요.");
}
@Test
void register_fail_invalid_gender(){
RegisterRequest request = createRequest("test@example.com", "test1234!", "test", "1999", "01012341234", null);
assertThatThrownBy(()->memberService.register(request))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("성별을 올바르게 입력해주세요.");
}
@Test
void register_fail_present_email(){
//given
RegisterRequest registerMember = createRequest("test@example.com", "test1234!", "test", "1999", "01012341234", Gender.SECRET);
memberService.register(registerMember);
RegisterRequest request = createRequest("test@example.com", "test1234", "test", "1999", "01012341234", Gender.MEN);
assertThatThrownBy(() -> memberService.register(request))
.isInstanceOf(MemberPresentException.class)
.hasMessageContaining("이미 가입된 이메일입니다.");
}
@Test
void register_success(){
//given
RegisterRequest registerMember = createRequest("success@example.com", "test1234!", "test", "1999", "01012341234", Gender.SECRET);
//when
Long memberId = memberService.register(registerMember);
//then
assertThat(memberId).isEqualTo(1L);
}
private RegisterRequest createRequest(String email, String password, String name, String birthYear, String phoneNo, Gender gender){
return new RegisterRequest(email, password, name, birthYear, phoneNo, gender);
}
}문제의 메소드는 register_success입니다. 메소드 단위 테스트를 진행할 때는 아무런 문제가 되지 않지만, 메소드 전체를 한번에 테스트를 진행할 때
org.opentest4j.AssertionFailedError:
expected: 1L
but was: 2L
예외가 터집니다.
테스트 코드에서는 h2 인메모리 db를 사용하고 있습니다. 분명 @Transactional 애노테이션까지 붙여서 롤백될텐데 왜 롤백이 안 되는지 ㅠㅠ..
그래서 생각한 건 테스트 코드에 @beforeEach 애노테이션으로 영속성 컨텍스트를 flush 시키는 방법인데, 현재 저는 Spring Data Jpa를 사용하고 있어서 entityManager.flush()를 사용하기에는 애로사항이 있습니다.
public interface MemberRepository extends JpaRepository<Member, Long> {
Optional<Member> findByEmail(String email);
}
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)테스트코드에 위의 애노테이션을 붙이는 방법도 있던데, 이렇게 하면 메소드를 실행할 때마다 컨텍스트를 초기화해서 너무 느리더라고요.
어떻게 하면 좋을까요?
답변 1
0
안녕하세요, 인프런 AI 인턴이에요.
Spring Data JPA에서 flush() 메서드는 EntityManager 인터페이스를 구현한 EntityManagerFactory의 createEntityManager() 메서드를 통해 EntityManager를 생성 후, EntityManager의 flush() 메서드를 이용해서 사용할 수 있습니다.
즉, EntityManager 객체를 생성 후, 해당 EntityManager의 flush() 메서드를 호출하면 영속성 컨텍스트의 상태를 데이터베이스에 동기화할 수 있습니다.
그리고 보시면 Test 클래스에서 @Transactional 어노테이션이 선언되어 있는데, 이것은 해당 메서드가 호출된 후에 자동으로 롤백된다는 의미입니다. 따라서, flush() 메서드 호출 후에 롤백된 상태로 동작하기 때문에 해당 메서드를 테스트하기 어려울 수 있습니다.
해결 방법으로는, @Transactional 어노테이션을 클래스 수준에서 선언하거나, flush() 메서드 호출 이후에 테스트를 진행하는 다른 메서드를 추가하는 것입니다.
참고하시기 바랍니다. 감사합니다.
인증이 늦었습니다ㅜㅜ 확인부탁드립니다
0
10
1
9월 8일 세션 진행한 거는 없었을까요
0
15
1
CertificationServiceTest
0
8
0
FlushModeType.COMMIT (12:45) 예시코드 질문
0
16
1
미션1 진행방법 관련
1
18
1
클로드코드 명령어 - 대화&세션관리부분 강의자료 빈폴더
0
20
1
Spock given and가 검증을 하는지
0
17
1
Issuance 테이블에 status, couponId 인덱스가 꼭 필요할까요?
2
28
1
readme에 대한 자료는 따로 받아볼수 있나요?
0
29
2
InvalidCurriculumException DIP 적용 여부 문의
0
26
1
섹션2, 대화&세션관리 수업 자료 누락
0
35
2
영상 다운로드는 안되나요?
0
45
1
IntelliJ IDEA 체험 만료
0
43
2
부하 테스트 시 설정 관련 질문드립니다
1
68
2
HelloSpringApplication.java 클래스 실행 오류
0
45
1
build 시 에러 해결방법 공유(docker.desktop 업데이트 -> 의존성 버전 수정)
0
61
2
예외처리 3강 문의
0
57
1
챌린지 시작일 문의
0
56
0
Inner class로 Config를 지정하는 이유
0
39
1
26년2회 실기기출은 언제쯤...
0
88
2
네이버 API | '검색 - 책' API 제공 중단
0
65
2
ArticleReadService 관련 질문
0
39
1
kafka 이벤트 발행 실패 시 at-least-once를 보장하는 방법이 궁금합니다.
1
94
1
이론 공부법 요약본 버전 업데이트 문의
0
65
2





