오늘은 저번 글에 이어 Repository를 테스트 하는 방법을 알아보겠습니다.
기존에 local에서 서버 테스트를 할 때 h2DB를 쓰기 때문에 jpa테스트를 진행할 때는 별개의 db를 사용하기 위해서 property 파일에 사용할 DB명시가 필요합니다.
저희 프로젝트에서는 yml 파일로 설정을 관리하기 때문에 application-testdb.yml 이라는 파일에 db정보를 넣어주겠습니다.
spring: #test DB??
config:
activate:
on-profile: test
datasource:
driver-class-name: org.h2.Driver
username: 'sa'
password:
url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;
jpa:
show-sql: 'true'
hibernate:
ddl-auto: create-drop
h2:
console:
enabled: true
- url: jdbc:h2:mem:test : 테스트가 실행되는 동안에만 DB데이터가 살아있으면 되기 때문에 인메모리 휘발성DB로 설정하기 위해 h2:mem으로 설정한다.
다음으로 test클래스를 만들겠습니다. (Intellij에서는 ctrl+alt+t 단축키를 누르면 test패키지의 같은 경로에 테스트 클래스를 만들어줍니다.)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) //별개의 DB설정을 적용하기 위한 어노테이션
@TestPropertySource("classpath:application-testdb.yml") // test용 DB설정한 설정파일 세팅
class ObservationRepositoryTest {
@Autowired
private ObservationRepository observationRepository;
@Test
void findByObservationName() {
String observationName = "관측지1";
Observation observation = getObservation(observationName);
observationRepository.save(observation);
Observation result = observationRepository.findByObservationName(observationName);
Assertions.assertEquals(result, observation);
}
}
- @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) 기본값으로 세팅된 db가 아닌 직접 설정한 별도의 DB를 사용하고 싶다면 해당 어노테이션을 붙여야 기본값을 덮어 사용할 수 있다.
사실 이렇게만 완료하면 테스트는 저번 글에 작성했던 것처럼 원하는 대로 Assertion라이브러리를 사용해서 작성하면 됩니다. 아주 간단한 만큼 이제 테스트를 설정하면서 만났던 오류를 공유하겠습니다.
- Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException : Error creating bean with name 'observationRepositoryCustomImpl' defined in file
별헤는밤 서버에서는 커스텀 쿼리 작성을 위해 Jpa 이외에도 QueryDsl을 사용하고 있는데요, queryDsl을 사용해서 쿼리를 작성한 RepositoryCustomImpl을 찾지 못해서 발생하는 오류입니다.
이를 해결하기 위해서는 QueryDsl을 설정하는 config파일을 테스트에도 설정해주면 됩니다.
@Import(QuerydslConfiguration.class) // 생성한 QueryDslConfig파일
class ObservationRepositoryTest {}
이렇게 까지 완료하면 아래처럼 각 클래스위에 수많은 어노테이션이 붙게 됩니다.
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@TestPropertySource("classpath:application-testdb.yml")
@Import(QuerydslConfiguration.class)
@ActiveProfiles("test")
class ObservationRepositoryTest {}
매번 각 repository테스트마다 이 수많은 어노테이션을 붙이는 것은 일부를 누락할 수도 있고 무엇보다 미관 상 좋지 않습니다. 그래서 커스텀 어노테이션을 만들어 Repository 테스트를 만들 때 필요한 모든 어노테이션을 하나로 축약하도록 하겠습니다.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@TestPropertySource("classpath:application-testdb.yml")
@Import(QuerydslConfiguration.class)
@ActiveProfiles("test")
public @interface DatabaseTest {
}
- @Retention : 어노테이션이 유지되는 기간
- SOURCE: 애노테이션이 소스 코드에서만 존재하며, 컴파일 시에 제거. 주로 컴파일러에 정보 제공 용도로 사용
- CLASS: 애노테이션이 컴파일된 클래스 파일에 포함되지만, JVM에서는 유지되지 않음. 주로 바이트코드 분석 도구에서 사용
- RUNTIME: 애노테이션이 런타임 동안 JVM에 의해 유지됩니다. 일반적으로 Spring이나 JUnit 같은 프레임워크에서 애노테이션이 필요한 경우 사용
- @Target : 어노테이션이 적용될 수 있는 Java 요소
- TYPE: 클래스, 인터페이스 또는 열거형에 적용됩니다.
- FIELD: 필드에 적용됩니다.
- METHOD: 메서드에 적용됩니다.
- PARAMETER: 메서드의 매개변수에 적용됩니다.
- CONSTRUCTOR: 생성자에 적용됩니다.
- ANNOTATION_TYPE: 다른 애노테이션에 적용됩니다.
- PACKAGE: 패키지에 적용됩니다.
위 두개의 어노테이션을 추가한 후 Repository단 테스트시에 필요한 어노테이션을 추가하면 다음과 같이 간결하게 사용할 수 있습니다.
@DatabaseTest
class ObservationRepositoryTest {
테스트 코드 관련 글을 마치면서 아주 작은 저만의 팁을 공유하겠습니다.
1. 메소드명을 먼저 작성하자.
저는 테스트코드명은 한국어로 작성하는 편인데 아무래도 무엇을 테스트하는지 한번에 보기가 편하기 때문입니다.
void 관측지조회_실패_관측지없음(){}
void 관측지조회_성공_단건(){}
void 관측지조회_성공_다건(){}
이런식으로 메소드명을 먼저 작성하고 후에 속을 채우면 좀 더 쉽게 테스트코드를 작성할수 있습니다.
2. 실패 케이스를 항상 더 자세히 추가하자
보통 테스트케이스를 작성하시면서 성공케이스는 많이 잘 작성하시지만 실패케이스는 놓치기 좋습니다. 하지만 실패케이스를 자세히 적 는 것이 가드로직을 자세하게 하고 후에 운영하면서 오류를 덜 발생할 수 있도록 사전에 예방해주게 됩니다.
3. 로직을 작성하다 예상되는 엣지케이스는 미리미리 테스트코드 메소드명이라도 적어두자
사실 TDD를 많이들 추천하지만 시간도 많이 걸리고 현실적으로 활용하기가 쉽지는 않습니다. 하지만 로직을 작성할 때 미리 테스트클래 스를 만들고 엣지케이스들을 잊지 않고 챙겨주기만 해도 조금은 더 안정적인 코드를 작성할 수 있습니다!
오늘은 Repository테스트 작성하는 법을 알아보았습니다.
이렇게 스프링부트의 service, repository단에 대한 테스트 코드 작성법을 모두 알아보았는데요.
처음에는 테스트 코드 작성하는 것이 귀찮겠지만 익숙해지면 직접 서버를 실행해서 테스트하기 전에 자세한 테스트로 미리 오류를 방지할 수 있어서 매우 좋습니다. 또한 테스트 코드는 리팩토링 시에 오류에 대한 개발자의 부담을 많이많이 덜어줍니다.
별헤는 밤 프로젝트도 아직은 테스트커버리지가 높지는 않지만 앞으로도 꾸준히 보완하여 더 안정적인 서버를 만들기 위해 노력하려고 합니다! 이 글을 읽는 분들도 귀찮으시겠지만 테스트코드 미리미리 작성하시기를 바랍니다.
'별밤 일지 > 개발' 카테고리의 다른 글
[Spring] Spring Scheduler 를 활용한 스케쥴러 만들기 (1) | 2024.10.14 |
---|---|
[flutter] Flutter 민감정보 숨기기 (0) | 2024.10.01 |
[Flutter] 우리는 언제 GestureDetector가 필요할까? (2) | 2024.09.23 |
[Flutter] macOS에서 vscode로 flutter 개발환경 구축하기 (0) | 2024.06.10 |
[Java] JsonPath, ObjectMapper (0) | 2024.06.10 |