Building more complex objects may come in handy when testing business systems. This can be done using jqwik’s Combinators
feature, which we’ll use in the following listing. Imagine that we have the following Book
class, and we need to generate different books for a property-based test.
Listing 5.21 A simple Book
class
public class Book {
private final String title;
private final String author;
private final int qtyOfPages;
public Book(String title, String author, int qtyOfPages) {
this.title = title;
this.author = author;
this.qtyOfPages = qtyOfPages;
}
// getters...
}
One way to do this would be to have a property test that receives three parameters: a String
for title
, a String
for author
, and an Integer
for quantity
of
pages
. Inside the property test, we would instantiate the Book
class. Jqwik offers a better way to do that, as shown in the next listing.
Listing 5.22 Using the Combinators
API to generate complex objects
public class BookTest {
@Property
void differentBooks(@ForAll("books") Book book) {
// different books!
System.out.println(book);
// write your test here!
}
@Provide
Arbitrary<Book> books() {
Arbitrary<String> titles = Arbitraries.strings().withCharRange(
➥ 'a', 'z')
.ofMinLength(10).ofMaxLength(100); ❶
Arbitrary<String> authors = Arbitraries.strings().withCharRange(
➥ 'a', 'z')
.ofMinLength(5).ofMaxLength(21); ❶
Arbitrary<Integer> qtyOfPages = Arbitraries.integers().between(
➥ 0, 450); ❶
return Combinators.combine(titles, authors, qtyOfPages)
.as((title, author, pages) -> new Book(title, author, pages)); ❷
}
}
❶ Instantiates one arbitrary for each of the Book’s fields
❷ Combines them to generate an instance of Book
The Combinators
API lets us combine different generators to build a more complex object. All we have to do is to build specific Arbitrary
s for each of the attributes of the complex class we want to build: in this case, one Arbitrary<String>
for the title, another Arbitrary<String>
for the author, and one Arbitrary<Integer>
for the number of pages. After that, we use the Combinators.combine()
method, which receives a series of Arbitrary
s and returns an Arbitrary
of the complex object. The magic happens in the as()
method, which gives us the values we use to instantiate the object.
Note how flexible jqwik is. You can build virtually any object you want. Moreover, nothing prevents you from building even more realistic input values: for example, instead of building random author names, we could develop something that returns real people’s names. Try implementing such an arbitrary yourself.
Leave a Reply