This article covers how to create sample random Data for your REST Services using a well-known library Data Faker. We will show how to bind a Fake Model to our Entity so that you can create sample Test Data in a snap!
In the first article of this series ( Generating Random data for REST Services: Part one ) we have learned how to use some linux command line tools to test our REST Services using curl. This approach is plain and simple however it does not provide realistic data for our Services.
Introducing DataFaker Java Testing Library
DataFaker goes beyond the conventional approach of using static or manually crafted data for testing. It enables developers and QA engineers to create dynamic and lifelike datasets on-the-fly, ensuring a more accurate representation of real-world scenarios.
Firstly, to get started with DataFaker you need to provide a single Library to your application:
<dependency> <groupId>net.datafaker</groupId> <artifactId>datafaker</artifactId> <version>1.9.0</version> </dependency>
Once that you have the library in your Classpath then you can create an instance of Faker and use it to produce random data for any of the available Providers. For example, to use the Name provider which belongs to the Base Provider Group you can just do the following:
import net.datafaker.Faker; Faker faker = new Faker(); String name = faker.name().fullName(); String firstName = faker.name().firstName(); String lastName = faker.name().lastName();
This example, however, is just scratching the surface. You can do much more. For example, you can bind one of your Beans with a Schema from Data Faker. In the next section we will learn how to do it.
Faking Entity Bean Data
In this example, we will use DataFaker in the context of a Jakarta EE application to demonstrate how useful it can be in the testing phase. Let’s begin by adding the @FakeForSchema in our Entity Class:
@Entity @FakeForSchema("com.mastertheboss.model.CustomerSchema#defaultSchema") public class Customer { @Id @SequenceGenerator( name = "customerSequence", sequenceName = "customerId_seq", allocationSize = 1, initialValue = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "customerSequence") private Long id; @Column(length = 40) private String name; @Column(length = 40) private String surname; // Getters/Setters omitted for brevity }
The @FakeForSchema
annotation specifies a schema for generating fake data using the Java Faker library. The schema defines the structure and constraints of the desired data, ensuring that it adheres to specific rules and patterns.
Then, let’s create the schema by adding the com.mastertheboss.model.CustomerSchema
Class:
public class CustomerSchema { public static Schema<Object, ?> defaultSchema() { var faker = new Faker(Locale.getDefault(), ThreadLocalRandom.current()); return Schema.of( field("name", () -> faker.name().firstName()), field("surname", () -> faker.name().lastName()) ); } }
The CustomerSchema
Class contains the mapping between the Customer Entity and the Faker Providers. As you can see, we are mapping name with the firstName()
function and surname with lastName()
.
Our application also includes a Repository Class to perform operations against the Database and a Controller which maps each of these operations. This application part does not however contain any change so you can just grab it from the source download link.
Coding the Test Client
Then, after deploying the server application we will code a client to Test it. For this purpose, we will be using RESTAssured which is a great fit for testing REST Content.
If you are new to RESTAssured we recommend checking this article: How to test REST Services with RestAssured
@BeforeAll public static void start() throws Exception { RestAssured.baseURI = "http://localhost:8080/datafaker/rest"; } @Test public void testRandomData() throws Exception { Customer client = BaseFaker.populate(Customer.class); // Convert the Java object to JSON ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(client); // Create and execute the POST request Response response = RestAssured .given() .contentType("application/json") .body(json) .post("/customers"); // Verify the response status code response.then().statusCode(201); Response response2 = RestAssured.given() .contentType(ContentType.JSON) .when() .get("/customers") .then() .extract().response(); Assertions.assertEquals(200, response2.statusCode()); System.out.println(response2.jsonPath().prettify()); RestAssured.given() .when().get("/customers") .then() .statusCode(200); }
The most interesting part is the following line of code:
Customer client = BaseFaker.populate(Customer.class);
In practice, we are creating a new Customer object using the CustomerSchema
structure that our Entity knows about. This way, our Customer object already contains all the properties we need for testing! By adding one GET subsequent Request we can verify that Customer list:
Moving the Fake Logic on the Client side
In this example, our Schema sits on the server side and matches with the Entity Bean. That’s great if your server side structure seldom changes. If you prefer, you can define the Schema on the Client side as well. For example, you can define your Schema in the Test Class much the same way:
BaseFaker faker = new BaseFaker(new ThreadLocalRandom.current()); Schema<Object, ?> schema = Schema.of( field("name", () -> faker.name().firstName()), field("surname", () -> faker.name().lastName()) ); JsonTransformer<Object> transformer = JsonTransformer.builder().build(); String json = transformer.generate(schema, 1); Response response = RestAssured .given() .contentType("application/json") .body(json) .post("/customers");
Also notice here we are using a Transformer Class to create JSON Content from the Schema. There are several built-in Transformers ( CSV,JSON, SQL, YAML, XML, Java Object) which you can use to produce directly the content in a particular format.
Using Sequences
Finally, it is worth mentioning that you can also build Collection of your data using the collection static method:
List<String> names = faker.collection( () -> faker.name().firstName(), () -> faker.address().streetAddress()) .len(2, 5) .generate(); System.out.println(names);
The above example will generate from 2 to 5 random attributes from the one mentioned. For example, in our case:
[Darron, Monty, 014 Abbott Crossroad, 6683 Keena Junctions]
Conclusion
DataFaker seamlessly integrates with popular testing frameworks, making it easy to incorporate dynamic data generation into your existing test suites. Whether you are using JUnit, TestNG, or another framework, DataFaker plays well with others, enhancing the versatility of your testing ecosystem.
Many thanks to Sergey Nuyanzin for providing tips on how to use Random Data Generation in my example!
Source code: https://github.com/fmarchioni/mastertheboss/tree/master/test/datafaker