Fixture Monkey란?
나는 새로운 프레임워크, 라이브러리 등을 공부할 때 꼭 도큐먼트부터 찾아간다.
블로그 글 여럿 보는 것보다 Docs 한 번이 더 도움 된다.
게다가 Fixture Monkey는 네이버에서 개발된 라이브러리인 만큼 한국어도 지원한다!
그래서 픽쳐 몽키란 무엇인가?
Fixture Monkey는 테스트 객체를 쉽게 생성하고 조작할 수 있도록 고안된 Java 및 Kotlin 라이브러리입니다.
내 식으로 말하자면 "테스트 코드 객체 생성 노가다를 줄여주는 라이브러리"이다.
종속성
- JDK 1.8 이상 (또는 Kotlin 1.8 이상)
- JUnit 5 platform
build.gradle
testImplementation 'com.navercorp.fixturemonkey:fixture-monkey-starter:1.0.14'
테스트 객체 생성 전략
객체 생성 전략은 FixtureMonkey 인스턴스를 만들 때 정의할 수 있다.
기본 객체 생성 전략은 BeanArbitraryIntrospector이다.
FixtureMonkey fixtureMonkey = FixtureMonkey.create();
FixtureMonkey fixtureMonkey = FixtureMonkey.builder()
+ options...
.build();
FixtureMonkey.create()를 사용하면 기본 전략인 BeanArbitrayIntrospector로 설정된다.
builder를 통해 직접 객체 생성 전략을 정의할 수 있다.
FixtureMonkey 인스턴스를 생성할 때 말고 테스트 객체를 생성할 때도 .giveMeBuilder와 .instantiate를 통해 생성 방법을 지정할 수도 있는데 자세한 내용은 아래 페이지에서 확인할 수 있다.
1. setter + 기본 생성자를 사용할 경우
@Getter
@Setter
@ToString
public class PostCreateRequestDto {
@NotBlank
private String title;
@NotBlank
private String contents;
}
기본 생성자와 setter를 사용할 경우에는 BeanArbitraryIntrospector 생성 전략을 사용한다.
FixtureMonkey fixtureMonkey = FixtureMonkey.create();
FixtureMonkey fixtureMonkey = FixtureMonkey.builder()
.objectIntrospector(BeanArbitraryIntrospector.INSTANCE)
.build();
FixtureMonkey.create()로 인스턴스를 만들어도 되고,
아래에 BeanArbitraryIntrospector.INSTANCE로 정의해 줄 수도 있다. (결과는 같다.)
2. builder를 사용할 경우
builder를 사용할 경우에는 BuilderArbitraryIntrospector 생성 전략을 사용한다.
FixtureMonkey fixtureMonkey = FixtureMonkey.builder()
.objectIntrospector(BuilderArbitraryIntrospector.INSTANCE)
.build();
3. 주어진 생성자 사용 + Lombok 사용
주어진 생성자를 사용하며 Lombok을 사용한다면 ConstructorPropertiesArbitraryIntrospector 생성 전략을 사용할 수 있다.
대신 lombok.config 파일에 lombok.anyConstructor.addConstructorProperties=true를 추가해야 한다.
lombok.config는 최상단에 파일을 생성하면 된다.
이 기능은 생성자에 @ConstructorProperties를 추가해주는 역할을 한다.
FixtureMonkey fixtureMonkey = FixtureMonkey.builder()
.objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE)
.build();
4. 리플렉션을 사용
FieldReflectionArbitraryIntrospector
FixtureMonkey fixtureMonkey = FixtureMonkey.builder()
.objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE)
.build();
5. 두 개 이상의 생성 전략 사용
FailoverArbitraryIntrospector
FixtureMonkey sut = FixtureMonkey.builder()
.objectIntrospector(new FailoverIntrospector(
Arrays.asList(
FieldReflectionArbitraryIntrospector.INSTANCE,
ConstructorPropertiesArbitraryIntrospector.INSTANCE
)
))
.build();
테스트 객체 생성
giveMeOne() - 객체 하나 생성
특정 타입 인스턴스를 하나 생성할 때는 giveMeOne()을 사용한다.
Product product = fixtureMonkey.giveMeOne(Product.class);
List<String> strList = fixtureMonkey.giveMeOne(new TypeReference<List<String>>() {});
인자로 클래스 혹은 타입이 들어간다.
giveMe() - 객체 여러 개 생성
특정 타입 인스턴스를 여러 개 생성할 때는 giveMe()를 사용한다.
스트림 또는 리스트를 생성한다.
Stream<Product> productStream = fixtureMonkey.giveMe(Product.class);
Stream<List<String>> strListStream = fixtureMonkey.giveMe(new TypeReference<List<String>>() {});
List<Product> productList = fixtureMonkey.giveMe(Product.class, 3);
List<List<String>> strListList = fixtureMonkey.giveMe(new TypeReference<List<String>>() {}, 3);
인자로 클래스 혹은 타입은 필수이며, 크기를 지정할 수도 있다.
giveMeBuilder() - 인스턴스 커스텀
인스턴스를 커스텀 할 때는 giveMeBuilder()를 사용한다.
PostCreateRequestDto requestDto = fixtureMonkey.giveMeBuilder(PostCreateRequestDto.class)
.set("title", "제목")
.set("contents", "내용")
.sample();
인자로 클래스 혹은 타입이 들어간다.
giveMeBuilder 메서드는 ArbitraryBuilder를 반환하는데 set 메서드를 통해 필드 내용을 직접 정의할 수 있다.
sample 메서드로 해당 클래스 객체를 반환받는다.
커스터마이징
기본적으로 아~주 랜덤한 값이 주어진다.
심지어 간헐적으로 null 값이 들어가기도 해서 골치가 아팠었다.
내가 뭘 잘못한 줄 ㅠㅠ
null, not null을 적용하거나 size를 제한하는 등 Validation에 필요한 내용을 적용하고 싶다면
커스터마이징 기능을 사용하면 된다.
대표적으로 Null, NotNull 기능을 살펴보자.
fixtureMonkey.giveMeBuilder(Product.class)
.setNull("id");
fixtureMonkey.giveMeBuilder(Product.class)
.setNotNull("id");
giveMeBuilder에서 설정해 줄 수 있다.
커스터마이징 부분은 기능이 많기 때문에 자세한 내용은 docs를 참고하자.
사용 후기
직접 값을 세팅해 줄 때보다 여러 케이스를 테스트할 수 있을 뿐만 아니라 코드가 굉장히 깔끔해졌다.
사용 법도 간단하고 무엇보다도 Docs사 한국어기 때문에 앞으로 테스트 코드를 작성할 때 항상 사용하게 될 것 같다.
'Spring' 카테고리의 다른 글
QueryDSL의 null처리 (0) | 2024.09.23 |
---|---|
[Spring] JPA 심화 강의 정리 (3) | 2024.06.26 |
[Spring] DB 테스트 환경 분리 (0) | 2024.06.13 |
[Spring] AOP란 무엇일까? (+Spring AOP) (0) | 2024.06.12 |
[Spring] JUnit 5 단위 테스트 (0) | 2024.06.11 |