Spock
개요
우리가 테스트 코드를 작성할 때 주로 쓰는 프레임워크는 xUnit으로 단위테스트 프레임워크를 말한다. 자바에서는 Junit이라는 프레임워크를 사용한다.
그럼 혹시 JUnit외에 다른 단위테스트 프레임워크는 없을까?
Spock
Spock는 BDD프레임워크로 기대하는 동작과 테스트 목적을 더 명확하게 작성할 수 있는 프레임워크다.
Groovy언어를 사용하여 테스트 코드를 작성하며 JUnit에 비해 더 간결하게 작성할 수 있고 JUnit에서 제공하는 주요 기능 모두를 지원하고있다.
Junit을 이용해 작성했을 때
@Test
void 테스트() {
// Given
String sample = null;
// When & Then
String result = sampleService.doSomething();
assertThat(result).isEqualTo(sample);
}
Spock를 이용해 작성했을 때
def "샘플 테스트 케이스"() {
given:
def sample = null
when:
def result = sampleService.doSomething()
then:
result == null
}
특징으로는 메소드 이름을 문자열로 작성할 수 있다는 점과 원래는 주석으로 gwt패턴을 나타냈다면 Spock에서는 코드블록을 선언하여 나타낼 수 있다.
테스트 메소드는 def를 이용하여 함수로 선언하고 하나 이상의 블록이 존재해야한다.
- given : 테스트에 필요한 값을 준비한다.
- when : 테스트할 코드를 실행한다.
- then : 예외 및 결과 값을 검증한다.
- expect : than과 같고 where를 필요로하지 않아서 간단한 테스트 및 where과 같이 사용한다.
- where : 데이터가 다르고 로직이 동일한 경우 동일한 테스트에 대한 중복 코드를 제거할 수 있다.
사용법
Spock를 사용하기 위해 플러그인과 의존성을 추가해야한다.
plugins {
id 'groovy`
id `java`
}
testImplementation 'org.spockframework:spock-core:2.4-M4-groovy-4.0'
testImplementation 'org.spockframework:spock-spring:2.4-M4-groovy-4.0'
implementation 'net.bytebuddy:byte-buddy:1.14.18'
이렇게 기본 의존성인 core와 스프링에서 사용하기 위해 spring의존성을 추가해주고 런타임에 클래스 기반 mock을 만들기 위해 buddy의존성을 추가해준다.
Testcontainers
단위테스트는 보통 service 계층을 대상으로 하고 실제 스프링 컨테이너를 띄워서 테스트할 경우 @SpringBootTest
애노테이션을 붙여서 테스트한다.
이렇게 할 경우 실제 데이터베이스를 사용하여 테스트가 수행되는데 테스트 환경에서 데이터베이스를 사용하는 방법은 여러가지가 있다.
- 개발환경 DB사용하기
- 인메모리 DB사용하기(H2)
- 테스트 컨테이너 사용하기
1번의 경우 실제 DB환경과 비슷한 환경에서 하기 때문에 실제 환경에서도 비슷하게 동작할 것이라는 기대를 할 수 있지만 동시 다발적으로 테스트할 경우 어느 테스트코드에선 데이터를 삭제하고 다른 테스트코드에선 그 데이터를 조회한다면 테스트 코드를 실행할 때마다 다른 결과가 나올 수 있다.
2번의 경우 메모리에서 실행되기 때문에 빠른 테스트 속도를 기대할 수 있지만 실제 환경과 다른 스펙이기 때문에 운영환경에 대한 테스트를 수행해야하는 경우 실제 운영환경과 다른 결과를 얻을 수 있다는 단점이 있다.
테스트 컨테이너는 운영환경과 유사한 DB를 사용하고 독립적인 환경에서 테스트할 수 있는 방법이다.
테스트 코드가 실행될 때 도커 컨테이너를 이용해서 테스트히고 끝나면 컨테이너를 자동으로 정리해준다.
이제 테스트 컨테이너에 대해 자세히 알아보자
일단 의존성을 추가해주어야한다.