이전에도 한번 테스트코드를 작성했지만 부족한 개념을 정리하기 위해 내용을 정리해보려고 합니다.
우선 이번에 하려는 부분은 repository만 단독으로 단위테스트를 진행하는 것입니다.
DB같은 경우 local에 있는 MySQL을 이용하려고 합니다.
대충 순서를 알아보면
- 필요한 가짜 객체 생성
- 가짜 객체 DB에 저장.
- 메서드 실행
- 결과 검증
이 순서대로 진행이 됩니다. 검증 이후 데이터는 롤백이 돼서 DB에서 삭제되는 방향으로 진행됩니다.
여기서 사용하려는 어노테이션의 정보입니다.
@DataJpaTest
- jpa환경에서 repository를 테스트하기 위해 spring에서 제공하는 어노테이션.
- 최소한의 스프링 컨텍스트를 제공한다.
- jpa entity 테스트를 위해 EntityManager와 TestEntityManager를 제공한다.
- 트랜잭션 경계 내에서 실행되기에 자동 롤백이 진행된다.
테스트를 진행할 쿼리
// 인증번호 일치 확인
@Query("select e from EmailConfirm e where e.certificationNumber = :code and e.certificationStatus = false")
Optional<EmailConfirm> checkCode(@Param("code") String code);
인증번호를 파라미터로 넘겨 false인 상태의 코드를 찾는 메서드입니다.
@Autowired
private EmailConfirmRepository emailConfirmRepository;
private EmailConfirm savedEmailConfirm;
@BeforeEach
void setUp(){
EmailConfirm emailConfirm = EmailConfirm.builder()
.certificationNumber("djid#sdfi0")
.certificationStatus(false).build();
savedEmailConfirm = emailConfirmRepository.save(emailConfirm);
}
우선 사용할 repository를 필드 주입으로 주입을 진행한 뒤, 사용할 Entity 하나를 미리 만들어둡니다.
@BeforeEach를 사용하면 해당 메서드는 매 테스트마다 자동으로 실행되는 영역입니다. 즉 매 테스트마다 emailConrim을 하나 만들고 save를 진행합니다.(데이터를 찾아야하기에 미리 만들어서 저장 해두는 것)
@Test
@DisplayName("사용하지 않고 일치하는 인증번호 검색")
void checkCode(){
// given
String code = "djid#sdfi0";
// when
Optional<EmailConfirm> findEmailConfirm = emailConfirmRepository.checkCode(code);
// then
Assertions.assertTrue(findEmailConfirm.isPresent());
Assertions.assertEquals(savedEmailConfirm, findEmailConfirm.get());
}
이후 메서드의 테스트코드입니다.
given : 테스트를 위한 준비
when : 어떤 테스트를 진행할지 명시
then : 결과 검증
given / when / then 패턴이 가시성도 좋아서 많이 이용하는 패턴입니다.
이렇게 실행하면 Failed to replace DataSource with an embedded database for tests. 바로 에러가 터지네요
이유는 @DataJpaTest는 기본적으로 임베디드 데이터베이스를 설정하는데, 아무것도 설정하지 않아서 발생하는 에러. 즉 DB 연결이 안 됐다는 내용입니다. MySQL을 사용한다고 했지만 설정을 하지 않았던 것.
이전에는 실제 DB에 연결해서 테스트를 진행했지만, 설정등의 이유로 테스트 시간이 느려진다는 특징이 있습니다.
그래서 이번에는 인메모리 H2 DB를 이용한 테스트 진행해보려고 합니다.
먼저 H2 의존성을 추가해줍니다.
gradle의 경우
testImplementation 'com.h2database:h2'
maven의 경우
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
이후 테스트용 application-test.yml을 따로 만들어야 합니다.
(main 경로에 만들면 안되고, test 경로에 resources 따로 만들어서 넣어야 합니다. 안 그러면 못 읽는 문제 발생)
spring:
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: sa
password:
jpa:
database-platform: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: create-drop
properties:
hibernate:
format_sql: true
show_sql: true
테스트용 yml 작성
이후 최상단 Test에 @TestPropertySource(locations = "classpath:application-test.yml") 어노테이션을 달아줍니다.
이후 동작을 시켜보면
성공적으로 repository 테스트를 진행할 수 있습니다!
'프로젝트 > RESTAPI 추천 서비스' 카테고리의 다른 글
MySQL 버퍼 풀 사이즈 조정으로 count 쿼리 성능 개선(37초 -> 0.026초) (1) | 2024.04.08 |
---|---|
50만개 데이터를 어떻게 페이징을 해볼까 (2) | 2024.04.07 |
RESTFUL API 서비스에서 쿠폰을 발행하자(동시성 문제 해결) (1) | 2024.03.30 |
너무 많은 요청을 제한해야 한다...(feat 세마포어로 스레드 제한) (0) | 2024.03.25 |