DummyMaker is a library that generates random Java Classes / Records / Sealed Interfaces / Sealed Classes for you.
Library can even do simple export in CSV/JSON/XML/SQL formats.
Library have no dependencies.
Gradle
implementation "com.github.goodforgod:dummymaker:4.0.0"
Maven
<dependency>
<groupId>com.github.goodforgod</groupId>
<artifactId>dummymaker</artifactId>
<version>4.0.0</version>
</dependency>
There are plenty of use cases where DummyMaker is useful:
Simple example on how you would create class with random data using constructor manually:
Street street = new Street(12, 1, "Revolution Sq");
Address address = new Address(street, "123456", "Saint-Petersburg");
Person person = new Person("Foo", "Bar", "foo.bar@ya.ru", address);
And if classes do not provide constructors with parameters:
Street street = new Street();
street.setNumber(12);
street.setType(1);
street.setName("Revolution Sq");
Address address = new Address();
address.setStreet(street);
address.setZipCode("123456");
address.setCity("Saint-Petersburg");
Person person = new Person();
person.setFirstName("Foo");
person.setLastName("Bar");
person.setEmail("foo.bar@ya.ru");
person.setAddress(address);
Using DummyMaker library, it is easy to generate Person class with all inner classes with random data for all fields:
GenFactory factory = GenFactory.build();
Person person = factory.build(Person.class);
GenFactory provides different methods for random class generation.
Given such Java Class as a model:
class User {
public String name;
public String surname;
}
Example on how to generate single random Java Class with random field values:
GenFactory factory = GenFactory.build();
User user = factory.build(User.class);
Example on how to generate standard Java Class (can be used with most of the standard Java Classes):
GenFactory factory = GenFactory.build();
Integer integer = factory.build(Integer.class);
Example how to generate list of Java Classes:
GenFactory factory = GenFactory.build();
List<User> users = factory.build(User.class, 1000);
Example how to generate stream of Java Classes:
GenFactory factory = GenFactory.build();
factory.stream(User.class, 1000)
.forEach(System.out::println);
In case have complex constructor, or it is required to generate on instantiated class, you can provide Supplier for factory:
GenFactory factory = GenFactory.build();
User user = factory.build(() -> new User());
GenFactory Builder provides different methods to configure random class generation and generated data specifications.
Example how to configure GenFactory, check its Builder for more settings:
class Account {
public String type = "simple";
public String name;
}
GenFactory factory = GenFactory.builder()
.overrideDefaultValues(false)
.applyCase(NamingCases.UPPER_CASE)
.build();
Account account = factory.build(Account.class);
Available configurations:
Case
- apply naming case for String values like SnakeCase, CamelCase, UpperCase, etc.Localisation
- choose language for generated String values (available Russian & English)Seed
- set seed to use when selecting random generator for fields for constant results across executionsAutoByDefault
- generate field values for all classes by default (true by default)DepthByDefault
- set maximum depth when generating random embedded classesIgnoreExceptions
- ignore exceptions while generating field values (false by default)OverrideDefaultValues
- generate random values for fields when field have Not Null value (true by default)GenFactory allows to provide rules for configuring class generation for specific fields.
Rules can be used to configure specific generators for specific fields or exclude fields.
GenRule examples will be based on this class:
class Account {
public Integer number;
public String type;
public String name;
}
Example on how to generate specific random value for any field:
List<String> values = Arrays.asList("1", "5", "9");
GenFactory factory = GenFactory.builder()
.addRule(GenRule.ofClass(Account.class)
.generateForNames("type", () -> CollectionUtils.random(values)))
.build();
Account account = factory.build(Account.class);
Class specific Rule is applied only for specific Class.
Example how to add specific Generator for fields by their names:
GenFactory factory = GenFactory.builder()
.addRule(GenRule.ofClass(Account.class)
.generateForNames("type", "name", () -> new NameGenerator()))
.build();
Account account = factory.build(Account.class);
Global Rule is applied for all Classes.
Example how to add specific Generator for all types:
GenFactory factory = GenFactory.builder()
.addRule(GenRule.ofGlobal()
.generateForTypes(String.class, () -> new NameGenerator()))
.build();
Account account = factory.build(Account.class);
Library provides lots of annotations to mark out class for random value generation.
This is an alternative to GenRules mechanism for random value generation configuring.
Check io.dummymaker.annotation package for all of them.
Using annotations like @GenEmail
, @GenId
, @GenName
, etc., it allows mark out which Generator to use for which field.
class Account {
@GenId
private String id;
@GenName
private String name;
@GenInt(from = 1, to = 10)
private long number;
@GenAddress
private String address;
@GenEmail
private String email;
}
GenFactory factory = GenFactory.build();
Account account = factory.build(Account.class);
Library provides annotations that allow to provide special behavior when generating random values of typically used for complex values generation:
@GenSequence
- generates sequence number value (when each individual field value should be incremented by 1).@GenArray
- generates random array value.@GenArray2D
- generates random double array value.@GenEnum
- generates random Enum value (should be annotated for Enum fields)@GenList
- generates random List value.@GenSet
- generates random Set value.@GenMap
- generates random Map value.@GenTime
- generates random Time value java.time.* package and old Java Data API.@GenUnixTime
- generates random UnixTime in millis.Configuration annotations:
@GenIgnore
- indicates that field will be excluded from random value generation.@GenAuto
- indicates that class should be Auto generated (generators swill be automatically selected if not marked out)@GenDepth
- configures maximum Depth when generating embedded class values.@GenAuto
@GenDepth(2)
class Account {
@GenSequence
private Long id;
@GenTime
private String timestamp;
@GenUnixTime
private long unixTime;
@GenIgnore
private String ignored;
@GenList
private List<String> emails;
@GenSet(generator = TypeGenerator.class)
private Set<String> types;
@GenMap
private Map<Integer, String> numbers;
private Account boss;
}
GenFactory factory = GenFactory.build();
Account account = factory.build(Account.class);
Library provides lots of GenAnnotations:
Library provides lots of generators:
Library provides simple Exporter classes to export objects in CSV, JSON, XML and even SQL formats.
Each Exporter provides different methods to export single Java class, list of classes or stream of classes.
Exporter have different configurations, like naming case for field names, also custom Writer can be supplied for file writing.
Examples will be based on this class:
class Account {
public Integer number;
public String type;
public String name;
}
Library provides special export annotations:
@GenExportIgnore
- allow to ignore object’s field during export.@GenExportRename
- allow to rename Dummy export Field Name.JsonExporter can export Java classes in JSON format.
Example:
GenFactory factory = GenFactory.build();
List<Account> accounts = factory.build(Account.class, 2);
Exporter exporter = JsonExporter.build();
String json = exporter.exportAsString(accounts);
Result:
[
{"number":1657591124,"type":"invalid","name":"Palmer"},
{"number":1243742023,"type":"rejected","name":"Cindy"}
]
CsvExporter can export Java classes in CSV format.
Example:
GenFactory factory = GenFactory.build();
List<Account> accounts = factory.build(Account.class, 2);
Exporter exporter = CsvExporter.build();
String csv = exporter.exportAsString(accounts);
Result:
number,type,name
1032136236,rejected,Mike
338683126,failed,Jesus
XmlExporter can export Java classes in XML format.
Example:
GenFactory factory = GenFactory.build();
List<Account> accounts = factory.build(Account.class, 2);
Exporter exporter = XmlExporter.build();
String xml = exporter.exportAsString(accounts);
Result:
<AccountList>
<Account>
<number>189092582</number>
<type>invalid</type>
<name>Antonio</name>
</Account>
<Account>
<number>58523878</number>
<type>failed</type>
<name>Carlos</name>
</Account>
</AccountList>
SqlExporter can export Java classes in SQL format.
This is useful when you need to insert millions rows into SQL database, such insert query is one of the fastest ways.
Example:
GenFactory factory = GenFactory.build();
List<Account> accounts = factory.build(Account.class, 2);
Exporter exporter = SqlExporter.build();
String sql = exporter.exportAsString(accounts);
Result:
CREATE TABLE IF NOT EXISTS account(
number INT,
type VARCHAR,
name VARCHAR,
PRIMARY KEY (number)
);
INSERT INTO account(number, type, name) VALUES
(1682341022, 'failed', 'Megan'),
(2052081057, 'invalid', 'Tina');
When exporting to file, you can provide your own Writer implementation.
Example:
GenFactory factory = GenFactory.build();
List<Account> accounts = factory.build(Account.class, 2);
Exporter exporter = JsonExporter.builder().withWriter(name -> new SimpleFileWriter(false, name)).build();
exporter.exportAsFile(accounts);
Library allows easily create custom Generator or annotations.
Simple Generator that produce some random value.
Generator can specify pattern that will be used choose where to apply such Generator based on field name.
public class IntegerMyGenerator implements Generator<Integer> {
private final Pattern pattern = Pattern.compile("age|grade|group", CASE_INSENSITIVE);
@Override
public Pattern pattern() {
return pattern;
}
@Override
public Integer generate() {
return ThreadLocalRandom.current().nextInt(1, 101);
}
}
Generator sometimes require more context to use for random value generation, than it is possible to implement ParameterizedGenerator.
public final class MyParameterizedGenerator implements ParameterizedGenerator<String> {
@Override
public String get(@NotNull GenParameters parameters) {
return parameters.namingCase().apply("myValue");
}
@Override
public String get() {
return "myValue";
}
}
You can apply custom Generator not only using GenRules but also using @GenCustom
annotation.
@GenCustom
annotation require Generator
class Account {
@GenCustom(IntegerMyGenerator.class)
public String type;
}
AnnotationGeneratorFactory is used when you need to instantiate generate with arguments from annotation.
AnnotationGeneratorFactory must have zero argument constructor.
@GenCustomFactory
is used to indicate which factory for which annotation to use.
Given annotation:
@GenCustomFactory(CustomIntegerAnnotationGeneratorFactory.class)
@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface GenIntCustom {
@Range(from = Integer.MIN_VALUE, to = Integer.MAX_VALUE)
int from() default 0;
@Range(from = Integer.MIN_VALUE, to = Integer.MAX_VALUE)
int to() default Integer.MAX_VALUE;
}
Respected AnnotationGeneratorFactory should look like:
public final class IntegerAnnotationGeneratorFactory implements CustomIntegerAnnotationGeneratorFactory<GenIntCustom> {
@Override
public @NotNull Generator<Integer> get(GenIntCustom annotation) {
return new IntegerGenerator(annotation.from(), annotation.to());
}
}
Documentation for versions 3.X.X in this document.
Documentation for versions 1.X.X in this document.
This project licensed under the MIT - see the LICENSE file for details.