Engineering
Spock 살펴보기
2021년 2월 22일
원문에서 보기 ↗Spock이란?
- Spock은 BDD(Behaviour-Driven Development) 프레임워크입니다.
- TDD 프레임워크인 JUnit과 비슷한 점이 많으나, 기대하는 동작과 테스트의 의도를 더 명확하게 드러내주고 산만한 코드는 뒤로 숨겨주는 등의 큰 장점이 있습니다.
기존 JUnit의 단점
- 테스트 중복 코드가 많습니다.
- JUnit, Hamcrest, Mockito를 전부 알아야 코드를 이해할 수 있습니다.
Spock 세팅
이렇게 gradle이나 maven에 선언을 해주고 groovy 파일 생성 후 Specification 클래스를 상속받으면 spock을 사용할 수 있습니다.
Spock의 구성
Spock 공식 문서에서는 6개의 라이프 사이클을 소개하고 있습니다.
setup과 cleanup은 각각 JUnit에서의 @before,@after에 해당하는 기능을 하고 있습니다.
when은 테스트할 대상 코드를 실행합니다. then은 테스트할 대상 코드의 결과를 검증하는데 assert 문이 따로 필요 없고 이 블록 범위에선 한 줄 한 줄이 자동 assert가 됩니다.
expect는 when과 then을 합친 것으로 간단한 검증을 하기에 적합합니다. where의 경우는 개인적으로 JUnit에 비해 정말 편리하다고 느끼는 부분인데 expect나 when에서 테스트할 코드의 변수를 |로 구분해서 나열할 수 있습니다.
JUnit으로 같은 테스트를 작성할 경우 위와 같이 중복 코드가 많이 발생하게 됩니다.
Mock
테스트 시 정말 자주 사용하게 되는 mocking 또한 Spock에서 간단하게 처리할 수 있습니다.
given 블록의 첫 줄처럼 간단하게 mocking 할 수 있으며 반환 값은 >>로 지정해 줄 수 있습니다.
만약 exception을 처리해야 한다면 위와 같이 작성할 수 있습니다.
Bean의 mocking
Spock을 쓴다 하더라도 Spring의 Bean을 mocking하려면 Mockito 방식을 사용해야 합니다.
하지만 이 경우 groovy 언어의 특성상 Overloading Method를 mocking할 때 어떤 메서드를 mocking 해야 할지 선택하지 못해 mocking 실패로 테스트가 실패하게 됩니다.
그럴 경우 Spock에서 제공하는 DetachedMockFactory 팩토리를 통한 Mock 생성을 통해 bean에 대한 mock 생성이 가능합니다. 하지만 이 경우에도 문제가 있는데 JpaRepository의 경우 mocking하지 못합니다. 때문에 JpaRepository 인터페이스 mocking이 필요할 경우 JUnit 또는 Spock에서 Mockito를 사용해야 합니다.
Spock 후기
조사를 시작하면서 처음 다가왔던 부분은 Spock이 저에게는 조금 생소한 언어였던 groovy 언어를 사용하는데 사실 크게 다른 부분은 보이지 않아서 언어의 문제보다는 테스트 코드 작성의 편리함이 더 크게 느껴졌습니다. 아무래도 기존에 많이 접해왔던 JUnit과 비교를 할 수밖에 없는데 Spock이 가지는 강점은 검증 문서의 편리함도 있었지만, 가장 좋았던 부분은 where 블록을 통한 코드 중복의 최소화였습니다. 기존에 테스트를 하다 보면 하나의 프로세스에 대해서 여러 가지 경우로 테스트를 하게 되는데 그런 경우 코드 중복을 확실하게 줄일 수 있는 Spock을 사용하면 좋을 것 같습니다. 하지만 bean을 mocking 하게 될 경우 조사하면서 mocking이 제대로 되지 않아 고생한 것도 있고 해결하지 못한 부분도 있기 때문에 그런 부분에서는 확실하게 숙지하기 전까지는 JUnit을 사용하는 것이 좀 더 안정적일 것 같습니다.