이전 글에서 BuilderGroup 추가에 대해서 제대로 설명하지 않고 넘어가서 따로 정리했다.
fun fixtureMonkeyBuilder(
objectMapper: ObjectMapper = JsonMappers.OBJECT_MAPPER
): FixtureMonkeyBuilder = KFixtureMonkeyBuilder()
.defaultGenerator(JacksonArbitraryGenerator(objectMapper))
.registerGroup(BuilderGroup::class.java)
위 코드 마지막줄에서 registerGroup 에 들어가는 BuilderGroup 클래스를 보자. 아래 코드를 보면 fixture 한개를 셋팅했다. RegisterProduct 객체를 fixture monkey 로 만드는데, 테스트를 위해 고정된 값을 따로 지정했다. fixture monkey 는 기본적으로 모든 필드를 랜덤한 값으로 채운다. 하지만 특정 기능을 테스트 하기 위해서 고정된 값이 필요할 때도 있다. 그 작업을 여기서 한다.
@Suppress("unused")
class BuilderGroup {
fun registerProduct(fixture: FixtureMonkey): ArbitraryBuilder<RegisterProduct> =
fixture.giveMeBuilder(RegisterProduct::class.java)
.set("no", 1234L)
.minSize("products", 1)
.set("products[*].productId", "ybs")
.specAny(
ExpressionSpec()
.setNull("products[*].case1")
.setNotNull("products[*].case2"),
ExpressionSpec()
.setNotNull("products[*].case1")
.setNull("products[*].case2")
)
}
실제 사용하는 코드에서 fixture.giveMeBuilder(RegisterProduct::class.java) 로 RegisterProduct 객체를 만들면 위에 지정된 디폴트 셋팅으로 채워진다. RegisterProduct no 를 1234 로 고정하고 products 리스트는 최소 1개 이상이 되도록 설정했다. RegisterProduct 안의 Product 리스트도 products[*] 표현식으로 셋팅할 수 있다.
물론 사용하는 코드에서 추가적인 set 작업을 하게 되면 그 값으로 덮어 씌워지므로 BuilderGroup 은 어디까지나 디폴트 값을 지정하는 역할이다.
마지막으로 specAny 기능을 소개하겠다. RegisterProduct 비지니스 정책 상 Case1, Case2 둘 중 하나만 값이 채워진다고 가정해보자. 여러 도메인에서 공통 클래스로 같이 쓸 때 많이 발생하는 케이스 이기도 하다. fixture monkey 는 specAny 를 통해 Case1 을 null로 set 하면 Case2 를 notNull로 set 하거나 그 반대가 되도록 지원한다. Case1, Case2 중 어떤게 값이 채워질지는 랜덤하다.
@Value
@Builder
public class RegisterProduct {
long no;
@Builder.Default
List<Product> products = List.of();
@Value
@Builder
public static class Product {
String productId;
// 비지니스 정책 상 Case1 이 값이 있으면 Case2 는 항상 null이다.
Case1 case1;
// 비지니스 정책 상 Case2 가 값이 있으면 Case1 는 항상 null이다.
Case2 case2;
}
@Value
@Builder
public static class Case1 {
String id;
}
@Value
@Builder
public static class Case2 {
String id;
}
}
아래는 5개 RegisterProduct 객체를 출력한 결과다. 고정시킨 값과 아닌 값이 의도한 대로 채워졌음을 확인할 수 있고 RegisterProduct 리스트도 최소 1개 이상인것, 그리고 Case1 Case2 둘 중 하나만 존재함을 확인할 수 있다.
RegisterProduct(no=1234, products=[RegisterProduct.Product(productId=ybs, case1=RegisterProduct.Case1(id=zK=as=Z1*2i)D4~OQa=%U@gEmYb?VIge1zvP`sq[%K+7_R&Ct60lB7z3pH{>~{}`g+b<QX,K2#X@C%6To+I$^cpyG/^>EjY.FF) R 'YC@?G%" |yO), case2=null), RegisterProduct.Product(productId=ybs, case1=RegisterProduct.Case1(id=), case2=null), RegisterProduct.Product(productId=ybs, case1=RegisterProduct.Case1(id=T~f'*|O$v1iZBKR), case2=null)])
RegisterProduct(no=1234, products=[RegisterProduct.Product(productId=ybs, case1=RegisterProduct.Case1(id={H@+OSDSg0*up), case2=null)])
RegisterProduct(no=1234, products=[RegisterProduct.Product(productId=ybs, case1=RegisterProduct.Case1(id=6S2Sau[sn\ 76]), case2=null), RegisterProduct.Product(productId=ybs, case1=RegisterProduct.Case1(id=), case2=null), RegisterProduct.Product(productId=ybs, case1=RegisterProduct.Case1(id=_cOfm), case2=null)])
RegisterProduct(no=1234, products=[RegisterProduct.Product(productId=ybs, case1=null, case2=RegisterProduct.Case2(id=K'p(Y2Eo<$C|bM)), RegisterProduct.Product(productId=ybs, case1=null, case2=RegisterProduct.Case2(id=J^B&))])
RegisterProduct(no=1234, products=[RegisterProduct.Product(productId=ybs, case1=RegisterProduct.Case1(id=k'Y(C|tV&i), case2=null), RegisterProduct.Product(productId=ybs, case1=RegisterProduct.Case1(id=}TRUiX h8BFeRiSaz), case2=null), RegisterProduct.Product(productId=ybs, case1=RegisterProduct.Case1(id=f+), case2=null)])
'Kotlin' 카테고리의 다른 글
DID 스터디 3회차(kotlin let/run/also/apply/with) (0) | 2023.03.18 |
---|---|
코틀린 재귀호출 최적화(Tail-Call) (0) | 2021.12.16 |
fixture monkey 로 예외 발생 테스트 (0) | 2021.12.15 |
form data 를 string으로 변환하기 (0) | 2021.11.15 |