77 identifier : " faq"
88---
99
10- ### 생성된 문자열의 문자 범위를 제한하려면 어떻게 해야 할까요?
11- > 관련 질문 - 생성된 인스턴트 값의 범위를 제한할 수 있나요?
10+ ### 픽스쳐 몽키를 어떻게 시작하나요?
1211
13- 일반적으로 픽스처에 제약 조건을 추가하고자 한다면 ArbitraryBuilder와 함께 제공된 Fixture Customization API를 사용할 수 있습니다.
14- 그러나 각 생성된 기본 타입이 특정 제약 조건을 지키길 원하는 경우에는 [ ` javaTypeArbitaryGenerator ` 와 ` javaTimeTypeArbitraryGenerator ` ] ( ../../fixture-monkey-options/customization-options/#constraining-java-types ) 옵션을 사용할 수 있습니다.
12+ 픽스쳐 몽키는 랜덤 값을 가진 테스트 객체를 쉽게 생성할 수 있는 방법을 제공합니다. 다음과 같이 시작할 수 있습니다:
1513
16- ` javaTypeArbitaryGenerator ` 옵션을 사용하면 문자열 또는 정수와 같은 기본 타입의 초기값을 커스터마이징 할 수 있습니다. 인스턴트와 같은 시간 타입의 경우 ` javaTimeTypeArbitaryGenerator ` 옵션을 사용할 수 있습니다.
14+ {{< tabpane persist=false >}}
15+ {{< tab header="Java" lang="java">}}
16+ // FixtureMonkey 인스턴스 생성
17+ FixtureMonkey fixtureMonkey = FixtureMonkey.create();
1718
18- 이 옵션은 문자열 생성시 특정 범위의 문자만 사용하려는 경우나 시간 타입을 특정한 범위 내로 생성하려는 경우에 특히 유용합니다.
19+ // 랜덤 객체 생성
20+ Person person = fixtureMonkey.giveMeOne(Person.class);
21+ {{< /tab >}}
22+ {{< tab header="Kotlin" lang="kotlin">}}
23+ // FixtureMonkey 인스턴스 생성
24+ val fixtureMonkey = FixtureMonkey.create()
1925
20- ### 특정 값이 생성되지 않도록 하려면 어떻게 해야 하나요?
21- [ ` set() ` ] ( ../../customizing-objects/apis/#set ) 을 사용하여 값을 쉽게 지정할 수 있지만, 값을 지정하는 것이 아니라 특정 값이 생성되지 않도록 제외하고 싶은 경우가 있을 수 있습니다.
26+ // 랜덤 객체 생성
27+ val person = fixtureMonkey.giveMeOne<Person >()
28+ {{< /tab >}}
29+ {{< /tabpane>}}
30+
31+ ### 픽스쳐 몽키를 프로젝트에 어떻게 추가하나요?
32+
33+ Maven이나 Gradle 프로젝트에 쉽게 픽스쳐 몽키를 추가할 수 있습니다:
34+
35+ {{< tabpane persist=false >}}
36+ {{< tab header="Gradle (Kotlin)" lang="kotlin">}}
37+ implementation("com.navercorp.fixturemonkey:fixture-monkey:1.1.x")
38+ {{< /tab >}}
39+ {{< tab header="Gradle (Groovy)" lang="groovy">}}
40+ implementation 'com.navercorp.fixturemonkey:fixture-monkey:1.1.x'
41+ {{< /tab >}}
42+ {{< tab header="Maven" lang="xml">}}
43+ <dependency >
44+ <groupId>com.navercorp.fixturemonkey</groupId>
45+ <artifactId>fixture-monkey</artifactId>
46+ <version>1.1.x</version>
47+ </dependency >
48+ {{< /tab >}}
49+ {{< /tabpane>}}
50+
51+ ### 특정 필드만 값을 지정하고 나머지는 랜덤으로 생성하려면 어떻게 하나요?
52+
53+ ` set() ` 메서드를 사용하여 특정 필드의 값을 지정할 수 있습니다:
54+
55+ {{< tabpane persist=false >}}
56+ {{< tab header="Java" lang="java">}}
57+ Person person = fixtureMonkey.giveMeBuilder(Person.class)
58+ .set("name", "홍길동")
59+ .set("age", 25)
60+ .sample();
61+ {{< /tab >}}
62+ {{< tab header="Kotlin" lang="kotlin">}}
63+ val person = fixtureMonkey.giveMeBuilder<Person >()
64+ .setExpGetter(Person::getName, "홍길동")
65+ .setExpGetter(Person::getAge, 25)
66+ .sample()
67+ {{< /tab >}}
68+ {{< /tabpane>}}
69+
70+ ### List, Set, Map 같은 컬렉션의 크기를 어떻게 제어하나요?
71+
72+ ` size() ` 메서드를 사용하여 컬렉션의 크기를 제어할 수 있습니다:
73+
74+ {{< tabpane persist=false >}}
75+ {{< tab header="Java" lang="java">}}
76+ Person person = fixtureMonkey.giveMeBuilder(Person.class)
77+ .size("friends", 5) // friends 리스트의 크기를 5로 설정
78+ .sample();
79+
80+ // 크기 범위 설정
81+ Product product = fixtureMonkey.giveMeBuilder(Product.class)
82+ .size("tags", 2, 5) // tags 리스트의 크기가 2~ 5개가 됨
83+ .sample();
84+ {{< /tab >}}
85+ {{< tab header="Kotlin" lang="kotlin">}}
86+ val person = fixtureMonkey.giveMeBuilder<Person >()
87+ .setExpSize(Person::getFriends, 5) // friends 리스트의 크기를 5로 설정
88+ .sample()
89+
90+ // 크기 범위 설정
91+ val product = fixtureMonkey.giveMeBuilder<Product >()
92+ .setExpSize(Product::getTags, 2, 5) // tags 리스트의 크기가 2~ 5개가 됨
93+ .sample()
94+ {{< /tab >}}
95+ {{< /tabpane>}}
96+
97+ ### null 값은 어떻게 처리하나요?
2298
23- 예를 들어, 클래스에 Enum 타입의 필드가 있고 그 필드가 특정 값을 갖지 않게 하려면, 아래와 같이 [ ` set() ` ] ( .../.../customizing-objects/apis/#set ) 를 사용할 수 있습니다.
99+ ` nullInject ` 옵션을 사용하여 null 확률을 제어할 수 있습니다:
100+
101+ {{< tabpane persist=false >}}
102+ {{< tab header="Java" lang="java">}}
103+ // null 값이 없는 FixtureMonkey 생성
104+ FixtureMonkey fixtureMonkey = FixtureMonkey.builder()
105+ .nullInject(0.0) // null 확률을 0으로 설정
106+ .build();
107+
108+ // null 확률이 50%인 FixtureMonkey 생성
109+ FixtureMonkey fixtureMonkey = FixtureMonkey.builder()
110+ .nullInject(0.5) // null 확률을 50%로 설정
111+ .build();
112+
113+ // 특정 필드를 null로 설정
114+ Person person = fixtureMonkey.giveMeBuilder(Person.class)
115+ .set("address", null)
116+ .sample();
117+ {{< /tab >}}
118+ {{< tab header="Kotlin" lang="kotlin">}}
119+ // null 값이 없는 FixtureMonkey 생성
120+ val fixtureMonkey = FixtureMonkey.builder()
121+ .nullInject(0.0) // null 확률을 0으로 설정
122+ .build()
123+
124+ // null 확률이 50%인 FixtureMonkey 생성
125+ val fixtureMonkey = FixtureMonkey.builder()
126+ .nullInject(0.5) // null 확률을 50%로 설정
127+ .build()
128+
129+ // 특정 필드를 null로 설정
130+ val person = fixtureMonkey.giveMeBuilder<Person >()
131+ .setExpGetter(Person::getAddress, null)
132+ .sample()
133+ {{< /tab >}}
134+ {{< /tabpane>}}
135+
136+ ### 테스트를 재현 가능하게 만들려면 어떻게 해야 하나요?
137+
138+ 고정된 시드를 사용하여 테스트 실행 간에 동일한 데이터를 생성할 수 있습니다:
139+
140+ {{< tabpane persist=false >}}
141+ {{< tab header="Java" lang="java">}}
142+ // 고정된 시드로 FixtureMonkey 생성
143+ FixtureMonkey fixtureMonkey = FixtureMonkey.builder()
144+ .seed(123L)
145+ .build();
146+ {{< /tab >}}
147+ {{< tab header="Kotlin" lang="kotlin">}}
148+ // 고정된 시드로 FixtureMonkey 생성
149+ val fixtureMonkey = FixtureMonkey.builder()
150+ .seed(123L)
151+ .build()
152+ {{< /tab >}}
153+ {{< /tabpane>}}
154+
155+ JUnit에서는 ` @Seed ` 어노테이션을 사용할 수도 있습니다:
156+
157+ {{< tabpane persist=false >}}
158+ {{< tab header="Java" lang="java">}}
159+ @Test
160+ @Seed (123L)
161+ void testWithSeed() {
162+ Person person = fixtureMonkey.giveMeOne(Person.class);
163+ // 매번 동일한 Person이 생성됨
164+ }
165+ {{< /tab >}}
166+ {{< tab header="Kotlin" lang="kotlin">}}
167+ @Test
168+ @Seed (123L)
169+ fun testWithSeed() {
170+ val person = fixtureMonkey.giveMeOne<Person >()
171+ // 매번 동일한 Person이 생성됨
172+ }
173+ {{< /tab >}}
174+ {{< /tabpane>}}
175+
176+ ### 생성된 객체가 특정 조건을 만족하도록 하려면 어떻게 해야 하나요?
177+
178+ ` setPostCondition() ` 을 사용하여 조건을 만족하지 않는 생성된 객체를 필터링할 수 있습니다:
179+
180+ {{< tabpane persist=false >}}
181+ {{< tab header="Java" lang="java">}}
182+ // 성인만 생성되도록 함
183+ Person adult = fixtureMonkey.giveMeBuilder(Person.class)
184+ .setPostCondition(person -> person.getAge() >= 18)
185+ .sample();
186+
187+ // 특정 필드가 조건을 만족하도록 함
188+ Product product = fixtureMonkey.giveMeBuilder(Product.class)
189+ .setPostCondition("price", Double.class, price -> price > 0 && price < 1000)
190+ .sample();
191+ {{< /tab >}}
192+ {{< tab header="Kotlin" lang="kotlin">}}
193+ // 성인만 생성되도록 함
194+ val adult = fixtureMonkey.giveMeBuilder<Person >()
195+ .setPostCondition { it.age >= 18 }
196+ .sample()
197+
198+ // 특정 필드가 조건을 만족하도록 함
199+ val product = fixtureMonkey.giveMeBuilder<Product >()
200+ .setPostConditionExpGetter(Product::getPrice, Double::class.java) { it > 0 && it < 1000 }
201+ .sample()
202+ {{< /tab >}}
203+ {{< /tabpane>}}
204+
205+ ### 특정 값이 생성되지 않도록 하려면 어떻게 해야 하나요?
206+ 필터를 사용하여 ` set() ` 으로 특정 값을 제외할 수 있습니다:
24207
25208{{< tabpane persist=false >}}
26209{{< tab header="Java" lang="java">}}
27210
28211Product product = sut.giveMeBuilder(Product.class)
29- .set("productType", ArbitraryUtils.toCombinableArbitrary(Arbitraries.of(ProductType)).filter(it -> it != CLOTHING && it != ELECTRONICS)))
212+ .set("productType", ArbitraryUtils.toCombinableArbitrary(Arbitraries.of(ProductType)).filter(it -> it != CLOTHING && it != ELECTRONICS))
30213 .sample();
31214
32215{{< /tab >}}
@@ -39,38 +222,147 @@ val product = sut.giveMeBuilder<Product>()
39222{{< /tab >}}
40223{{< /tabpane>}}
41224
42- 혹은 일종의 필터처럼 동작하는 [ ` setPostCondition() ` ] ( ../../customizing-objects/apis/#setpostcondition ) 을 사용할 수 있습니다.
225+ 또는 필터처럼 동작하는 ` setPostCondition() ` 을 사용할 수 있습니다:
43226
44227{{< tabpane persist=false >}}
45228{{< tab header="Java" lang="java">}}
46229
47230Product product = sut.giveMeBuilder(Product.class)
48- .setPostCondition("productType", ProductType.class, it -> it != CLOTHING || it != ELECTRONICS)
231+ .setPostCondition("productType", ProductType.class, it -> it != CLOTHING && it != ELECTRONICS)
49232 .sample();
50233
51234{{< /tab >}}
52235{{< tab header="Kotlin" lang="kotlin">}}
53236
54237val product = sut.giveMeBuilder<Product >()
55- .setPostConditionExpGetter(Product::getProductType, ProductType::class.java) { it != ProductType.CLOTHING || it != ProductType.ELECTRONICS }
238+ .setPostConditionExpGetter(Product::getProductType, ProductType::class.java) { it != ProductType.CLOTHING && it != ProductType.ELECTRONICS }
56239 .sample()
57240
58241{{< /tab >}}
59242{{< /tabpane>}}
60243
61244` setPostCondition() ` 을 사용하면 Product 인스턴스가 생성된 후 필터링되므로 제한적인 조건에서 더 높은 비용이 발생할 수 있습니다. 이러한 경우 ` set() ` 을 대신 사용하는 것이 권장됩니다.
62245
246+ ### 중첩된 객체는 어떻게 처리하나요?
247+
248+ 픽스쳐 몽키는 중첩된 객체를 자동으로 생성합니다. 속성 경로를 사용하여 이러한 객체를 커스터마이징할 수 있습니다:
249+
250+ {{< tabpane persist=false >}}
251+ {{< tab header="Java" lang="java">}}
252+ Order order = fixtureMonkey.giveMeBuilder(Order.class)
253+ .set("customer.name", "홍길동")
254+ .set("customer.address.city", "서울")
255+ .size("items", 3)
256+ .set("items[ 0] .productName", "노트북")
257+ .sample();
258+ {{< /tab >}}
259+ {{< tab header="Kotlin" lang="kotlin">}}
260+ val order = fixtureMonkey.giveMeBuilder<Order >()
261+ .setExp("customer.name", "홍길동")
262+ .setExp("customer.address.city", "서울")
263+ .sizeExp("items", 3)
264+ .setExp("items[ 0] .productName", "노트북")
265+ .sample()
266+ {{< /tab >}}
267+ {{< /tabpane>}}
268+
63269### 필드 중 하나가 다른 필드의 값에 의존하고 있습니다. 이러한 픽스처를 커스터마이징 하려면 어떻게 해야 하나요?
64270
65- ` thenApply() ` 메서드는 다른 필드에 의존하는 필드를 커스터마이징 할 때 유용합니다. 자세한 내용은 [ ` thenApply() ` ] ( ../../customizing-objects/apis/#thenapply ) 을 확인해주세요.
271+ ` thenApply() ` 메서드는 다른 필드에 의존하는 필드를 커스터마이징 할 때 유용합니다:
272+
273+ {{< tabpane persist=false >}}
274+ {{< tab header="Java" lang="java">}}
275+ Money money = fixtureMonkey.giveMeBuilder(Money.class)
276+ .set("currency", Currency.getInstance("KRW"))
277+ .thenApply((m, builder) ->
278+ builder.set("amount", m.getCurrency().equals(Currency.getInstance("KRW")) ? 10000.0 : 100.0))
279+ .sample();
280+ {{< /tab >}}
281+ {{< tab header="Kotlin" lang="kotlin">}}
282+ val money = fixtureMonkey.giveMeBuilder<Money >()
283+ .setExpGetter(Money::getCurrency, Currency.getInstance("KRW"))
284+ .thenApply { money, builder ->
285+ builder.setExpGetter(Money::getAmount, if (money.currency == Currency.getInstance("KRW")) 10000.0 else 100.0)
286+ }
287+ .sample()
288+ {{< /tab >}}
289+ {{< /tabpane>}}
290+
291+ 자세한 내용은 [ ` thenApply() ` ] ( ../../customizing-objects/apis/#thenapply ) 를 확인해주세요.
292+
293+ ### 생성된 문자열의 문자 범위를 제한하려면 어떻게 해야 할까요?
294+ > 관련 질문 - 생성된 인스턴트 값의 범위를 제한할 수 있나요?
295+
296+ 각 생성된 기본 타입이 특정 제약 조건을 지키길 원하는 경우에는 [ ` javaTypeArbitaryGenerator ` 와 ` javaTimeTypeArbitraryGenerator ` ] ( ../../fixture-monkey-options/customization-options/#constraining-java-types ) 옵션을 사용할 수 있습니다.
297+
298+ {{< tabpane persist=false >}}
299+ {{< tab header="Java" lang="java">}}
300+ // 특정 문자 범위로 문자열 생성 설정
301+ FixtureMonkey fixtureMonkey = FixtureMonkey.builder()
302+ .javaTypeArbitraryGenerator(new JavaTypeArbitraryGenerator() {
303+ @Override
304+ public StringArbitrary strings() {
305+ return Arbitraries.strings().alpha().ofLength(5, 10);
306+ }
307+ })
308+ .build();
309+
310+ // 특정 범위로 시간 생성 설정
311+ FixtureMonkey fixtureMonkey = FixtureMonkey.builder()
312+ .javaTimeTypeArbitraryGenerator(new JavaTimeTypeArbitraryGenerator() {
313+ @Override
314+ public Arbitrary<Instant > instant() {
315+ Instant start = Instant.parse("2023-01-01T00:00:00Z");
316+ Instant end = Instant.parse("2023-12-31T23:59:59Z");
317+ return Arbitraries.instants().between(start, end);
318+ }
319+ })
320+ .build();
321+ {{< /tab >}}
322+ {{< tab header="Kotlin" lang="kotlin">}}
323+ // 특정 문자 범위로 문자열 생성 설정
324+ val fixtureMonkey = FixtureMonkey.builder()
325+ .javaTypeArbitraryGenerator(object : JavaTypeArbitraryGenerator() {
326+ override fun strings(): StringArbitrary {
327+ return Arbitraries.strings().alpha().ofLength(5, 10)
328+ }
329+ })
330+ .build()
331+
332+ // 특정 범위로 시간 생성 설정
333+ val fixtureMonkey = FixtureMonkey.builder()
334+ .javaTimeTypeArbitraryGenerator(object : JavaTimeTypeArbitraryGenerator() {
335+ override fun instant(): Arbitrary<Instant > {
336+ val start = Instant.parse("2023-01-01T00:00:00Z")
337+ val end = Instant.parse("2023-12-31T23:59:59Z")
338+ return Arbitraries.instants().between(start, end)
339+ }
340+ })
341+ .build()
342+ {{< /tab >}}
343+ {{< /tabpane>}}
66344
67345### 특정 타입을 생성할 때 예외가 발생해요
68346
69- 먼저 [ PriorityConstructorArbitraryIntrospector] ( ../../generating-objects/introspector/#PriorityConstructorArbitraryIntrospector ) 를 사용해보세요. 다음과 같이 사용할 수 있습니다.
70- ``` java
71- FixtureMonkey . builder()
347+ 특정 타입을 생성할 때 예외가 발생하면 [ PriorityConstructorArbitraryIntrospector] ( ../../generating-objects/introspector/#PriorityConstructorArbitraryIntrospector ) 를 시도해보세요:
348+
349+ {{< tabpane persist=false >}}
350+ {{< tab header="Java" lang="java">}}
351+ FixtureMonkey fixtureMonkey = FixtureMonkey.builder()
72352 .pushExactTypeArbitraryIntrospector(ProblematicType.class, PriorityConstructorArbitraryIntrospector.INSTANCE)
73353 .build();
74- ```
354+
355+ // 이제 생성이 잘 될 것입니다
356+ ProblematicType instance = fixtureMonkey.giveMeOne(ProblematicType.class);
357+ {{< /tab >}}
358+ {{< tab header="Kotlin" lang="kotlin">}}
359+ val fixtureMonkey = FixtureMonkey.builder()
360+ .pushExactTypeArbitraryIntrospector(ProblematicType::class.java, PriorityConstructorArbitraryIntrospector.INSTANCE)
361+ .build()
362+
363+ // 이제 생성이 잘 될 것입니다
364+ val instance = fixtureMonkey.giveMeOne<ProblematicType >()
365+ {{< /tab >}}
366+ {{< /tabpane>}}
75367
76368위 옵션을 추가했는데도 동작하지 않는다면, ` ArbitraryIntrospector ` 을 직접 만들거나 깃허브에 [ 이슈] ( https://github.com/naver/fixture-monkey/issues ) 를 만들어주시면 도움을 드리겠습니다.
0 commit comments