Skip to content

Generators

Samuel Beausoleil edited this page Mar 22, 2022 · 6 revisions

Generators are the heart of Factorium. A generator is simply a class that describes how to create a valid object of any desired type. To make your own generator, it is recommanded to extend the provided BaseGenerator<T> class. It provides a basic implementation that can handle most scenarios of modifiers and leaves you to focus on creating your object. Furthermore, it future-proofs your application against any possible changes as it is guaranteed that any class that extends it will only ever have to implement the make() method.

FakerGenerator

FakerGenerator is a base generator that additionnally provides a shared Faker instance for all your subclasses. You may configure it once and have it available with that configuration everywhere.

Here is an example of a simple POJO and it's associated generator:

public class City {
    private String name;
    private long nCitizens;

    public City(String name, long nCitizens) {
        this.name = name;
        this.nCitizens = nCitizens;
    }
...
}

public class CityGenerator extends FakerGenerator<City> {
    @Override
    protected City make() {
        return new City(faker.name().lastName(), Math.abs(faker.random().nextLong()) + 1);
    }
}

Usage

After having configured your generator, its usage becomes very simple:

CityGenerator generator = new CityGenerator();
City foo = generator.generate();

Additionally, you may generate as many unique objects as you want at once:

List<City> cities = cityGenerator.generate(15);

Specialized generators

You may have as many generators as you want for a given class. It is suggested to keep all of your generators for a type in the same file by using static nested classes, with the top level one being the default one.

public class CityGenerator extends FakerGenerator<City> {

    @Override
    protected City make() {
        return new City(faker.name().lastName(), Math.abs(faker.random().nextLong()) + 1);
    }

    public static class CapitalGenerator extends FakerGenerator<City> {

        @Override
        protected City make() {
            return new City(faker.country().capital(), Math.abs(faker.random().nextLong()) + 1);
        }
    }
}

Nesting generators

Sometimes we want to use a generator inside of an other one, like for complex objects. In that case, it is strongly recommanded to abstract away the actual type of the generator in its field. Like this:

public class AddressGenerator extends FakerGenerator<Address> {

    private Generator<City> cityGenerator = new CityGenerator();

    @Override
    protected Address make() {
        return new Address(
                faker.number().randomDigitNotZero(),
                faker.address().streetName(),
                faker.address().zipCode(),
                cityGenerator.generate()
        );
    }
}

This is so that if you decide to use a Provider to manage the generators across your application, it will be able to replace the nested generators with the appropriate transformed type.

Clone this wiki locally