DEV Community

Cover image for Instancio: Data Generator For Unit Tests
armandino
armandino

Posted on • Edited on

Instancio: Data Generator For Unit Tests

This post is about reducing manual data setup in unit tests. Typically such setup involves instantiating some classes and calling a bunch of setters. For example, in the the following test this is done in the createBookDTO() method:

Note: links to source code provided at the end.

// Class under test
private final BookMapper bookMapper = new BookMapper();

@Test
void map() {
    // Given
    BookDTO bookDto = createBookDTO();

    // When
    Book book = bookMapper.toEntity(bookDto);

    // Then
assertThat(book.getTitle()).isEqualTo(bookDto.getBookTitle());
    // ... snip ... remaining assertions
}

// Data setup
private BookDTO createBookDTO() {
     AuthorDTO authorDto = new AuthorDTO();
     authorDto.setAuthorId(UUID.randomUUID().toString());
     authorDto.setFirstName("Jane");
     authorDto.setLastName("Doe");

     BookDTO bookDto = new BookDTO();
     bookDto.setBookId(UUID.randomUUID().toString());
     bookDto.setIsbn("test-isbn");
     bookDto.setBookTitle("test-title");
     bookDto.setAuthor(authorDto);
     bookDto.setGenre(Genre.FICTION);
     bookDto.setPublishedOn(LocalDate.of(1865, 3, 17));
     bookDto.setNumberOfPages(123);
     bookDto.setPriceCents(3099);
     return bookDto;
}
Enter fullscreen mode Exit fullscreen mode

The setup done in createBookDTO() is very typical for unit tests. However, it can be quite tedious, especially when dealing with large classes. What's more is that often the values themselves don't actually matter. Whether you set the name to "Jane Doe" or "Foo Bar" makes no difference. The end result is the same.

If values don't matter, then why not use a library to create and populate an object with random data? This is exactly what Instancio does. It is a library that generates objects for unit tests. Using Instancio, we can create a BookDTO instance as follows:

private BookDTO createBookDTO() {
    return Instancio.create(BookDTO.class);
}
Enter fullscreen mode Exit fullscreen mode

This seems like a step in the right direction, but what if we need to customise some values of BookDTO? Let's say the BookMapper class that we are testing converts string UUID values to UUID type:

UUID.fromString(bookId) // need a valid UUID string!
Enter fullscreen mode Exit fullscreen mode

In this case, the test will fail unless our test objects contain valid ids (notice that setAuthorId() and setBookId() in the original createBookDTO() method are both set to UUID.randomUUID().toString()). To achieve this, we can use Instancio's builder API to set custom values:

Instancio.of(BookDTO.class)
    .set(field(BookDTO.class, "bookId"), UUID.randomUUID().toString())
    .set(field(AuthorDTO.class, "authorId"), UUID.randomUUID().toString())
    .create();
Enter fullscreen mode Exit fullscreen mode

For this simple test the above change is sufficient and now our test will pass. However, Instancio supports a number of other features for customising generated objects, for example:

Instancio.of(BookDTO.class)
    .generate(field("genre"), gen -> gen.oneOf(Genre.CRIME, Genre.SCIFI, Genre.FANTASY))
    .generate(field("isbn"), gen -> gen.text().pattern("#d-#d#d#d#d#d-#d#d#d-#d"))
    .generate(field("numberOfPages"), gen -> gen.ints().range(100, 999))
    .create();
Enter fullscreen mode Exit fullscreen mode

There might be a follow up article to go into more detail. Please leave a comment if you'd like to see more examples, or if you have any questions. All feedback is welcome!

If you are interested in learning more, please see the user guide which also has a number of examples.

You can find the book-mapper-sample project at https://github.com/instancio/instancio-samples

Links

Top comments (1)

Collapse
 
eawanmacen profile image
Info Comment hidden by post author - thread only accessible via permalink
eawanmacen

Work with lio app your team in real time by easily creating documents together and sharing the same with other users on Whatsapp, Gmail and other social apps.

Some comments have been hidden by the post's author - find out more