일전에 테스트만을 위한 코드 작성에 대한 생각을 작성한적이 있다.
이처럼 테스트를 위한 코드 변경을 지양하는 편이며 프러덕션코드와 요구사항의 스펙을 통일 하기 위하여 테스트 디렉토리에 Support Pakage 를 만들어 Builder나 Fixture, Fake Class등을 만들어놓고 사용했었다.
다만 이런 방식의 경우 멀티 모듈에서 각기 다른 모듈에서 import 할 수 없는 문제가 있었다. 모듈별로 Support 클래스를 따로 둘수 있지만 이는 동일한 코드를 반복적으로 작성해야하고, 번거로운 작업을 진행해야 한다.
이런 상황에서 java-test-fixtures 플러그인을 사용하면 중복을 효율적으로 관리하고 문제를 손쉽게 해결 할 수 있다.
storage 와 domain 모듈이 있다고 가정해겠다.
(* domain: 핵심 비지니스, storage: 데이터의 저장/수정/삭제)
domain 모듈의 있는 support 클래스를 storage 모듈에서도 사용하기 위해
//domain module
plugins {
id 'java-test-fixtures'
}
위와 같이 도메인 모듈에 java-test-fixtuers 플러그인을 추가한 후 {module-path}/src/testFixtures 디렉토리를 생성해준다.
해당 디렉토리에는 위치가 0이 아닌 자동차를 생성할 수 있는 빌더를 작성하였다.
public class CarBuilder {
private final String name;
private int position;
public CarBuilder(String name) {
this.name = name;
}
public CarBuilder position(int position) {
this.position = position;
return this;
}
public Car build() {
Car car = new Car(this.name);
for (int idx = 0; idx < position; idx++) {
car.move(() -> true);
}
return car;
}
}
storage 모듈의 build.gradle에 아래와 같이 의존성을 추가해 준다.
//storage module
dependencies {
implementation(project(":domain"))
testImplementation(testFixtures(project(":domain")))
}
이제 storage 모듈에서도 domain 모듈에서 정의한 CarBuilder를 사용 할수 있다.
public class InMemoryCarRepositoryTest {
private CarRepository repository = new InMemoryCarRepository();
@BeforeEach
void setup() {
Car car = new Car("seok2");
car.move(() -> true);
repository.save(car);
}
@Test
@DisplayName("자동차를 이름으로 조회한다.")
void findByName() {
Car car = repository.findByName("seok2");
Car expected = new CarBuilder("seok2")
.position(1)
.build();
assertThat(car).isEqualTo(expected);
}
}
위 예제의 사용한 소스 코드는 GitHub에서 확인할 수 있습니다.
java-test-fixtures 플러그인은 활용하면 테스트 코드를 위한 fixture 의 중복을 제거하고 재사용할 수 있다. 테스트코드는 프러덕션 코드 못지 않게 잘 관리되어야 한다고 생각한다. 테스트 코드를 잘 관리하는 방법에도 관심을 가지도록 하자.
테스트 빌더를 만들기 위해서 대상이 되는 객체의 내부 구조 및 동작에 대해서 자세하게 알고 있어야 하며 (;자동차를 전진시키기 위해서 자동차 내부 구조에 대한 이해가 필요하였다.) 다양한 케이스를 만들기 위해서 작성해야하는 코드의 양이 매우 많아진다. 리플렉션을 사용하여 작성되는 코드의 양을 줄일 수는 있지만 대상의 변경에 민감하게 반응하여 대상이 변경될때마다 테스트 코드를 많이 수정해야하는 경우가 생긴다.