Fork me on GitHub

Random values generation for testing purposes

Random values generation

The most basic value generation requires only passing the value type to the Generators.randomValue() method:

String value = Generators.randomValue(String.class);
assertNotNull(value);

If null values are acceptable call Generators.nullableRandomValue() method:

String value = Generators.nullableRandomValue(String.class);
// The generated value can be null or a random value

Parameterized values generation

Generators can support optional generation parameters implementing the dev.orne.test.rnd.params.ParameterizableGenerator interface. This allows fine-tuning the generated values:

String value = Generators.randomValue(
    String.class,
    GenerationParameters.forNullables().withNullable(false),
    GenerationParameters.forSizes().withMinSize(10));

Current built-in generation parameters:

Type Supported parameters types Required parameters types
java.lang.CharSequence Nullable, Size
java.lang.String Nullable, Size
java.lang.Collection Nullable, Size SimpleGenerics
java.lang.List Nullable, Size SimpleGenerics
java.lang.Set Nullable, Size SimpleGenerics
java.lang.Map Nullable, Size KeyValueGenerics

Collections generation requires, at least, the generic types parameters to success:

List<String> list = Generators.randomValue(
    List.class,
    GenerationParameters.forSimpleGenerics().withElementsType(String.class));
Map<String, Locale> map = Generators.randomValue(
    Map.class,
    GenerationParameters.forKeyValueGenerics()
        .withKeysType(String.class)
        .withValuesType(Locale.class),
    GenerationParameters.forSizes().withMaxSize(5));
Map<String, Map<Integer, String>> nestedMap = Generators.randomValue(
    Map.class,
    GenerationParameters.forKeyValueGenerics()
        .withKeysType(String.class)
        .withValuesType(TypeUtils.parameterize(Map.class, Integer.class, String.class)),
    GenerationParameters.forSizes().withMaxSize(5));

Targeted value generation

Targeted generators are generator instances that generate values for a target usage. Generators targeting bean properties, constructor parameters, method parameters and method return types are supported.

When a targeted generator generates values of a type whose registered generator is a parameterizable generator uses the runtime information of the target to populate the generation parameters. Currently the runtime ParameterizedType of the target and following validation constraints are supported:

  • javax.validation.constraints.NotNull
  • javax.validation.constraints.Size
  • javax.validation.constraints.Min
  • javax.validation.constraints.Max
  • javax.validation.constraints.PositiveOrZero
  • javax.validation.constraints.Positive

Examples:

// Property
TargetedGenerator<String> generator = Generators.forProperty(
        TestType.class,
        "name")
String value = generator.randomValue(MyValidationGroup.class);
// Constructor parameter
TargetedGenerator<String> generator = Generators.forParameter(
        MyBean.class,
        new Class<?>[] { String.class },
        0)
String value = generator.randomValue(MyValidationGroup.class);
// Method parameter
TargetedGenerator<String> generator = Generators.forParameter(
        MyBean.class,
        "myMethod",
        new Class<?>[] { String.class },
        0)
String value = generator.randomValue(MyValidationGroup.class);
// Method return type
TargetedGenerator<String> generator = Generators.forReturnType(
        MyBean.class,
        "myMethod",
        new Class<?>[] { String.class })
String value = generator.randomValue(MyValidationGroup.class);

Annotation based random values generation in JUnit 5 tests

The library provides a JUnit 5 extension to inject random values based in targeted value generation system. Add the @Random annotation to any field, constructor parameter, test life-cycle callback parameter, or test method parameter.

See targeted value generation and parameterized values generation for supported generation parameters extraction.

class MyTest {

    // Generated on @BeforeAll phase
    private static @Random Year staticNullableValue;
    // Generated on @BeforeAll phase
    private static @Random @NotNull Year staticNonNullValue;
    // Generated once per @BeforeEach phase
    private @Random Year instanceNullableValue;
    // Generated once per @BeforeEach phase
    private @Random @NotNull Year instanceNonNullValue;

    @BeforeAll
    static void beforeAllCallback(
            // Generated on invocation
            @Random String nullableValue,
            @Random @NotNull String nonNullValue) {
        assertNotNull(nonNullValue);
        assertNotNull(staticNonNullValue);
    }

    @AfterAll
    static void afterAllCallback(
            // Generated on invocation
            @Random String nullableValue,
            @Random @NotNull String nonNullValue) {
        assertNotNull(nonNullValue);
    }

    @BeforeEach
    void beforeEachCallback(
            // Generated on invocation
            @Random String nullableValue,
            @Random @NotNull String nonNullValue) {
        assertNotNull(nonNullValue);
        assertNotNull(instanceNonNullValue);
    }

    @AfterEach
    void afterEachCallback(
            // Generated on invocation
            @Random String nullableValue,
            @Random @NotNull String nonNullValue) {
        assertNotNull(nonNullValue);
        instanceValue = null;
    }

    RandomValueExtensionTest(
            // Generated on class instantation
            @Random String nullableValue,
            @Random @NotNull String nonNullValue) {
        assertNotNull(nonNullValue);
    }

    @Test
    void testSomething(
            // Generated once per invocation
            @Random String nullableValue,
            @Random @NotNull String nonNullValue) {
        assertNotNull(nonNullValue);
    }
}

Supported out-of-the-box types

  • Primitives and wrapper types
    • java.lang.Boolean
    • java.lang.Byte
    • java.lang.Short
    • java.lang.Integer
    • java.lang.Long
    • java.lang.Float
    • java.lang.Double
    • java.lang.Character
  • Common JRE types
    • java.lang.CharSequence
    • java.lang.Number
    • java.lang.String
    • java.io.File
    • java.math.BigInteger
    • java.math.BigDecimal
    • java.nio.charset.Charset
    • java.nio.file.Path
    • java.util.Calendar
    • java.util.Currency
    • java.util.Date
    • java.util.Locale
    • java.util.TimeZone
    • java.util.URI
    • java.util.URL
    • java.util.UUID
    • java.time.Clock
    • java.time.Duration
    • java.time.Instant
    • java.time.LocalDate
    • java.time.LocalDateTime
    • java.time.LocalTime
    • java.time.MonthDay
    • java.time.OffsetDateTime
    • java.time.OffsetTime
    • java.time.Period
    • java.time.Year
    • java.time.YearMonth
    • java.time.ZonedDateTime
    • java.time.ZoneId
    • java.time.ZoneOffset
    • java.time.chrono.Chronology
  • Arrays and collections
    • java.lang.Array
    • java.util.Collection
    • java.util.List
    • java.util.Set
    • java.util.Map
  • Enumerations
  • Annotated beans
    • Annotated constructor based bean generator
    • Annotated method based bean generator

Generic beans generation

Not every bean type requires a dedicated generator. For simple bean types annotation based generation is supported.

Annotated constructor based bean generation

Beans with a constructor annotated with @GeneratorMethod will be generated out-of-the-box calling the annotated constructor with targeted random arguments:

public class MyType {
    @GeneratorMethod
    public MyType(
            Integer paramA,
            String paramB) {
        super();
        // Populate bean
    }
}

Annotated method based bean generation

Alternatively, beans can annotate a factory method with @GeneratorMethod will be generated out-of-the-box calling the annotated method with targeted random arguments:

public class MyType {
    @GeneratorMethod
    public static @NotNull MyType factory(
            Integer paramA,
            String paramB) {
        MyType bean = new MyType();
        // Populate bean
        return bean;
    }
}