배경

TDD를 도입하면서 테스트코드 작성 중 가장 까다롭고 번거로운 부분 중 하나는 테스트용 객체를 일일이 생성하는 작업이다. 이를 자동화하여 테스트코드 작성의 진입 장벽을 낮추고, 생산성을 향상시키고자 하였다.

 관련 환경 및 요구 사항

  • 기존 시스템 및 테스트 환경과의 호환성 유지가 중요

    • Java 1.8

    • SpringBoot 2.5.1

    • Junit 5.7.2

  • 비즈니스 로직 및 DTO 등 기존 코드 변경을 최소화할 것

  • 복잡하고 중첩된 객체 구조도 자동 생성 가능해야 함

 고려한 옵션

Java 진영의 테스트용 객체 자동 생성 라이브러리 중 다음 두 가지를 비교 검토했다:

항목Fixture MonkeyInstancio
설명NAVER에서 개발한 객체 생성 도구. 복잡한 계층 구조의 객체 생성에 특화됨Java Bean 객체 자동 생성기. 간결한 문법과 유연한 커스터마이징, JPA 연관 객체 처리 지원
장점- Bean Validation 기반으로 제약 조건을 활용한 생성 가능

- Kotlin 테스트와의 호환성 우수
- 러닝 커브가 낮고 사용법이 직관적- 가볍고 빠름

- 공식 문서가 풍부하고 정리되어 있음
단점- 상대적으로 무거움- DSL과 Introspector 설정 학습 필요

- 기본 생성자 등의 요구 조건이 있음
- 복잡한 제약 조건은 수동 설정 필요

- Bean Validation 기반 조건 자동 추론은 어려움

두 라이브러리의 공통점

  • 모두 Java 테스트용 객체 자동 생성 도구

  • 복잡한 객체 구조 생성 가능 (중첩, 컬렉션 등)

  • 랜덤 데이터 생성 및 커스터마이징 기능 제공

  • Fluent 스타일 API 제공

  • 테스트 실패 시 재현 가능한 고정 시드(seed) 설정 지원

예제 코드 비교

Instancio 예시 코드

Person person = Instancio.create(Person.class);
 
Person personWithoutAgeAndAddress = Instancio.of(Person.class)
    .ignore(field(Person::getAddress))
    .create();
 

**Fixture monkey 예시 코드

FixtureMonkey fixtureMonkey = FixtrueMonkey.create();
 
Person person = fixtureMonkey.giveMeOne(Person.class);
Person personWithoutAgeAndAddress = fixtureMonkey.giveMeBuilder(Person.class)
    .setNull(javaGetter(Person::getAddress))
    .sample();

Fixture Monkey를 잘 활용하려면 Introspector라는 개념에 대해 알아야한다. 어떤 Introspector를 적용하냐에 따라 Fixture Monkey의 객체 생성 방식이 달라지게 된다.

사실 이 코드의 경우 클래스에는 인수가 없는 생성자와 setter가 있어야 한다. 기본 Introspector 설정인BeanArbitraryIntrospector 로 되어있기 때문이다.

이 외에도 4가지가 더 있으며, 테스트코드에 사용할 객체에 따라 다르게 Introspector 를 설정해주어야한다.

사용 경험 및 체감

Fixture Monkey의 경우는 Introspector 설정 외에도, 기존 코드에 기본 생성자 추가 등 번거로움이 많고 러닝 커브가 높은것으로 느껴졌다.

그에 반해 InstancioInstancio.create() 를 호출하게되면 리플렉션을 기반으로 알아서 생성자, getter/ setter 등을 활용하여 더 폭넓게 객체를 생성해주고 러닝커브가 상대적으로 낮아보인다.

 결론

Instancio는 기존 코드 변경 요구가 적고 러닝 커브가 낮아 테스트 코드 작성에 보다 적합하다고 판단하였다.
따라서 프로젝트의 테스트 객체 자동 생성 도구로 Instancio를 도입하고, 관련 예제 코드 및 가이드 문서를 함께 정리하여 공유할 예정이다.