
우선, Test Code (이하 테스트 코드) 에 대해 이야기 하기에 앞서 왜 Test Code 를 작성해야할까? 🤔
직접 테스트 코드를 작성하면서 느꼈던 점은 크게 다음과 같다.
- 구현 시, 예상하지 못한 예외 케이스를 catch 할 수 있다.
- 특정 상황에 대한 코드를 간편하게 구현하여 테스트할 수 있다.
특히 1번의 경우는 Fixture Monkey의 장점과 연관되어 있는 내용이라고 생각한다.
그렇다면 테스트 코드는 어떻게 작성할 수 있을까?
또한 테스트용 객체(a.k.a 목 객체)는 어떻게 생성할 수 있을까?
나와 같은 경우는 아래와 같은 3단계를 거쳐서 작성했었다.
1.
new생성자를 통한 객체 생성
2.@Builder를 통한 객체 생성
3.Fixture monkey를 통한 객체 생성
다음과 같은 도메인이 있다고 가정해보자.
public record Profile (
String name,
int age,
String gender
)
이 경우에 new 연산자를 통해 간단히 테스트용 객체를 생성할 수 있다.
Profile profile = new Profile(
"이은비",
20,
"여"
);
하지만, Profile 도메인 내부의 필드가 많아진다면?
public record Profile (
String name,
int age,
String gender,
int phoneNumber,
String adress,
int residentRegistrationNumber,
..
(etc)
)
결국 new 연산자를 사용한다면 모든 필드에 대해 값을 빠짐없이 넣어줘야 한다.
Profile profile = new Profile(
"이은비",
20,
"여",
01012345678,
"강남구",
001101,
..
);
특히, 테스트용 객체를 생성하다보면 필수값이 아닌 필드들에 대해서 값을 할당해주는 건 필요성을 느끼기 어려운 부분이다.
따라서 도메인 내의 모든 필드가 중요하기에 빠짐없이 작성해야 한다면 new 연산자를 사용하겠지만, 아니라면 Optional 하게 객체를 작성하고 싶은 경우가 자주 있다.
이럴 경우, @Builder 를 통해 객체를 생성할 수 있다.
최근까지 사용했던 방법이고, 많은 프로젝트에서 볼 수 있는 목 객체 생성 방법이다.
이 방법은 @Builder 어노테이션을 통해 간편하고, Optional 하게 필드에 대해 값을 할당할 수 있다.
다시 필드가 많은 버전의 Profile 도메인을 봐보자.
public record Profile (
String name,
int age,
String gender,
int phoneNumber,
String adress,
int residentRegistrationNumber,
..
(etc)
)
@Builder 를 통해 객체를 생성한다면 다음과 같다.
Profile profile = Profile.builder()
.name("이은비")
.age(20)
.gender("여")
.residentRegistrationNumber(001101)
.build();
특히, 위와 같이 필수 필드에 대해서 쉽게 값을 선택적으로 할당시켜줄 수 있다.
하지만 이렇게 작성할 경우, 내가 예상한 시나리오에 대해서만 테스트를 하는 느낌을 지울 수 없다.
즉, 놓칠 수 있는 예외 케이스에 대해서는 고려하지 못한 채 테스트를 진행하여 catch 할 수 없다는 것이다.
또한, 반복적으로 테스트를 작성하다보면 종종 null 이면 안되는 필드에 값을 할당해주지 않아서 NPE가 터지는 상황을 피할 수 없다.
이런 저런 고민 끝에 요즘 사용하기 시작한 테스트용 객체 작성 방법은 Fixture Monkey 이다.
Fixture Monkey 는 앞서 설명했던 단점들을 어느정도 해결해주는 방법이다.
특히 Fixture Monkey 에는 객체를 생성하는 방법이 여러 가지가 있는데, 주로 사용하는 방법은 giveMeBuilder() 이다.

사용 예시는 다음과 같다.
private final FixtureMonkey monkey = MonkeyBuilder.monkey(
ConstructorPropertiesArbitraryIntrospector.INSTANCE);
먼저 사용 전에 위와 같이 의존성 주입을 진행한다.
그리고, 다음과 같이 사용할 수 있다.
String name = "이은비";
int age = 20;
int residentRegistrationNumber = 001101;
Profile profile = monkey.giveMeBuilder(Profile.class)
.set("name", name)
.set("age", age)
.set("residentRegistrationNumber", residentRegistrationNumber)
.sample();
1️⃣ .giveMeBuilder() : 객체 생성을 진행할 클래스를 주입한다.
2️⃣ .set() : 값을 세팅할 필드를 "필드명, ${value} 형태로 작성한다.
3️⃣ .sample() : @Builder의 .build() 와 같이 객체 생성을 마무리한다.
또한, Fixture Monkey 특성 상 무작위로 값을 세팅 을 진행하기 때문에 null 까지 주입해준다.
따라서 특정 필드에 null 이 들어가면 안될 경우, .setNull() 을 통해 NPE 를 방지할 수 있다.
즉 Fixture Monkey 를 직접 사용해보면서 통해서 Test Code를 작성하는 2가지 장점을 느낄 수 있었다.
이 밖에도, 여러 메서드를 통해 목 객체를 생성할 수 있는데 (ex. giveMeOne, .. ) 본 내용은 다음 포스팅부터 공식 Docs 와 함께 자세히 다뤄보자! 😉
Good job