본문 바로가기
Java Spring

instancio 자바 스프링 테스트 객체(entity, dto) 빠르게 만들어 보자

by Bill Lab 2024. 12. 27.
728x90

단위테스트 코드를 짤때, DTO 나 entity 와 같은 object 단위를 생성하고 속성값들을 하나하나 씩 입력해줘야 했다.

또한 단위테스트를 수행할 때는 실제 data 를 고려하지 않는다.

(실제 data 와 유사한 data 를 직접 넣어주게 되는데, instancio 는 이러한 data 를 랜덤하게 자동 생성해준다.)

 

다양한 Data를 제공해주므로써 오히려, 테스트의 정확성도 높일 수 있다.

왜? 내가 지정한 Data에서는 잘돌아갈 수 있는데 다른 Data 에서는 이슈가 발생할 수도 있기때문이다.

이때 이슈 핸들링이 로직적으로 잘 수행되어있는지도 비지니스 레이어에서 처리가 되어야 하는데, instancio를 통해 이를 테스트 할 수 있기때문이다.

그렇다고 우리가 매번 다른 Data를 넣는것도 현실적으로 힘들다.

 

간단한 예시를 보겠다!

User user = Instancio.of(User.class)
               .set(field(User::getName), "name")   // 이름 고정
               .set(field(User::getEmail), "test@example.com")  // 이메일도 고정
               .generate(field(User::getAge), gen -> gen.ints().range(18, 30)) // 나이는 18세에서 30세 사이로 설정
               .create();

 

 

그럼 다시 본론으로 돌아가서 좀더 상세한 내용에 대해 아래와 같이 정리해보았다.

공식사이트 참고 : https://www.instancio.org/user-guide/#project-goals

 

1. Object 생성

//Shorthand methods
Instancio.create(Class<T> type)
Instancio.create(TypeTokenSupplier<T> supplier)
Instancio.create(Model<T> model)

//Builder API
Instancio.of(Class<T> type).create()
Instancio.of(TypeTokenSupplier<T> supplier).create()
Instancio.of(Model<T> model).create()

//Examples of create() methods
// Create by specifying the class
Person person = Instancio.create(Person.class);

// Using type tokens
Pair<String, Long> pair = Instancio.create(new TypeToken<Pair<String, Long>>() {});

Map<Integer, List<String>> map = Instancio.create(new TypeToken<Map<Integer, List<String>>>() {});

// Create from a model of person with the age field ignored
Model<Person> personModel = Instancio.of(Person.class)
    .ignore(field(Person::getAge))
    .toModel();

// Create a person from the model, and additionally ignore the address field
Person personWithoutAgeAndAddress = Instancio.of(personModel)
    .ignore(field(Person::getAddress))
    .create();

 

 

2. Collections 생성

 

//Collections API: using Class
Instancio.createList(Class<T> elementType)
Instancio.createSet(Class<T> elementType)
Instancio.createMap(Class<K> keyType, Class<V> valueType)


//Collections builder API: using Class
Instancio.ofList(Class<T> elementType).create()
Instancio.ofSet(Class<T> elementType).create()
Instancio.ofMap(Class<K> keyType, Class<V> valueType).create()


//Collections builder API: using TypeToken
Instancio.ofList(TypeTokenSupplier<T> elementType).create()
Instancio.ofSet(TypeTokenSupplier<T> elementType).create()
Instancio.ofMap(TypeTokenSupplier<K> keyType, TypeTokenSupplier<V> valueType).create()


//example
List<Person> list = Instancio.createList(Person.class);

List<Person> list = Instancio.ofList(Person.class).size(10).create();

List<Pair<String, Integer>> list = Instancio.ofList(new TypeToken<Pair<String, Integer>>() {}).create();

Map<UUID, Address> map = Instancio.ofMap(UUID.class, Address.class).size(3)
    .set(field(Address::getCity), "Vancouver")
    .create();

// Create from a model
Model<Person> personModel = Instancio.of(Person.class)
    .ignore(field(Person::getAge))
    .toModel();

Set<Person> set = Instancio.ofSet(personModel).size(5).create();

 

3. Record 나 Sealed Class 생성(version 확인용, 일반클래스와 동일)

Instancio version 1.5.0 introduced support for creating

record classes when run on Java 16+, and
sealed classes when run on Java 17+.

This uses the same API as described above for creating regular classes.

 

 

4. Steam of Objects

//Shorthand methods
Instancio.stream(Class<T> type)
Instancio.stream(TypeTokenSupplier<T> supplier)


//Stream Builder API
Instancio.of(Class<T> type).stream()
Instancio.of(TypeTokenSupplier<T> supplier).stream()


//Examples of stream() methods
List<Person> personList = Instancio.stream(Person.class)
    .limit(3)
    .collect(Collectors.toList());

Map<UUID, Person> personMap = Instancio.of(new TypeToken<Person>() {})
    .ignore(all(field(Person::getAge), field(Person::getAddress)))
    .stream()
    .limit(3)
    .collect(Collectors.toMap(Person::getUuid, Function.identity()));

 

 

5. Blank Objects 생성

//Shorthand method
Instancio.createBlank(Class<T> type)


//Builder API
Instancio.ofBlank(Class<T> type).create()


//Examples of creating blank objects
Person person = Instancio.createBlank(Person.class);

// Output:
// Person[name=null, address=Address[street=null, city=null, country=null]]

Person person = Instancio.ofBlank(Person.class)
    .set(field(Address::getCountry), "Canada")
    .create();

// Output:
// Person[name=null, address=Address[street=null, city=null, country=Canada]]

 

 

6. 단순 값 생성

공식사이트

 

URL url = Instancio.gen().net().url().get();

URI uri = Instancio.gen().net().uri().nullable().get();

String randomChoice = Instancio.gen().oneOf("foo", "bar", "baz").get();

List<LocalDate> dates = Instancio.gen().temporal().localDate().future().list(5);

List<String> uuids = Instancio.gen().text().uuid().upperCase().withoutDashes().list(5);

 

 

7. @InstancioSource 사용

@ExtendWith(InstancioExtension.class)
class ExampleTest {

    @ParameterizedTest
    @InstancioSource
    void singleArgument(Person person) {
        // snip...
    }

    @ParameterizedTest
    @InstancioSource
    void multipleArguments(Foo foo, Bar bar, Baz baz) {
        // snip...
    }
}

 

8. InstancioExtension 예시

@ExtendWith(InstancioExtension.class)
class ExampleTest {
    @Test
    void T1() {
        String t1 = Instancio.create(String.class); // Output: "FCGVRXSUU"
    }

    @Test
    void T2() {
        String t2 = Instancio.create(String.class); // Output: "FCGVRXSUU"
    }
}
728x90