Skip to content

How to override default settings

Introduction

Out of the box, Instancio is pre-configured with "sensible defaults". For example, when populating an object it will set fields to non-null values, create non-empty collections, generate positive numbers, etc. For cases where these defaults are not acceptable they can be modified as follows:

  • globally, using a configuration file
  • per test class using settings injection
  • per object using the API

This article provides on overview of how to achieve the above goals.

Settings API and default values

Instancio configuration is encapsulated by the Settings class which provides the API for modifying settings at runtime. This class is essentially a map of SettingKey objects and their values. A setting key represents a configuration item. It has a default value and a property name that can be used in a configuration file. The complete list of keys can be found in the Keys Javadoc. The following are a few examples:

  • Keys.COLLECTION_MAX_SIZE - specifies maximum size for collections
    • default value: 6
    • property name: collection.max.size
  • Keys.INTEGER_MIN - specifies minimum value for integers
    • default value: 1
    • property name: integer.min
  • Keys.STRING_NULLABLE - specifies whether a null can be generated for String type
    • default value: false
    • property name: string.nullable

The Settings class provides two static methods for creating an instance:

  • Settings.create() returns a new instance of blank settings
  • Settings.defaults() returns a new instance containing default settings

If no custom settings are provided, Instancio will use default settings as returned by Settings.defaults().

Overriding settings per object

Settings can be customised per object using the Settings class. For example, the following snippet creates a person allowing null and empty strings to be generated:

Example of custom settings per object
1
2
3
4
5
6
7
Settings settings = Settings.create()
    .set(Keys.STRING_NULLABLE, true)
    .set(Keys.STRING_ALLOW_EMPTY, true);

Person person = Instancio.of(Person.class)
    .withSettings(settings)
    .create();

Overriding settings per test class

Using InstancioExtension with JUnit 5 allows injecting settings into a test class. This can be achieved by annotating the Settings field with @WithSettings.

Example of custom settings per test class
@ExtendWith(InstancioExtension.class)
class ExampleTest {

    @WithSettings
    private final Settings settings = Settings.create()
            .set(Keys.COLLECTION_MIN_SIZE, 10);

    @Test
    void verifyPerson() {
        Person person = Instancio.create(Person.class);

        assertThat(person.getHobbies()).hasSizeGreaterThanOrEqualTo(10);
    }
}

The benefit of this approach is that all test methods within the class will use the specified settings. It is more concise as there is no need to call withSettings(settings) manually on each object.

Overriding settings globally using instancio.properties

Overriding settings globally can be done by placing a file named instancio.properties on the classpath. Instancio loads this file automatically and uses its values to override the defaults. For example, assuming we have the following file:

Example of instancio.properties
integer.min=0
integer.max=100

all integers generated by Instancio will be within the given range.

Person person = Instancio.create(Person.class);
assertThat(person.getAge()).isBetween(0, 100);

A sample properties file with available keys is provided in the user guide.

Configuration precedence

Since there are three ways to provide configuration, Instancio has the following precedence rules when resolving configuration values. From lowest to highest:

  • Configuration from instancio.properties
  • Configuration from @WithSettings
  • Configuration from withSettings()

As an example, assume we have this configuration file on the classpath:

instancio.properties
integer.min=10
integer.max=99

The properties file is loaded automatically from the classpath. Therefore the following snippet will generate a number in the 10..99 range.

1
2
3
4
5
6
7
8
9
@ExtendWith(InstancioExtension.class)
class SettingsPrecedenceExampleTest {

    @Test
    void overridingSettings() {
        int n = Instancio.create(Integer.class);
        assertThat(n).isBetween(10, 99);
    }
}

Next we will modify the above class to override the configuration by injecting Settings into the test class:

@ExtendWith(InstancioExtension.class)
class SettingsPrecedenceExampleTest {

    @WithSettings
    private final Settings settings = Settings.create()
            .set(Keys.INTEGER_MIN, 100)
            .set(Keys.INTEGER_MAX, 999);

    @Test
    void overridingSettings() {
        int x = Instancio.create(Integer.class);
        assertThat(x).isBetween(100, 999);
    }
}

Since @WithSettings has higher precedence than the properties file, the generated number x will be within the 100..999 range.

Finally, we will override settings by passing an instance via the API:

@ExtendWith(InstancioExtension.class)
class SettingsPrecedenceExampleTest {

    @WithSettings
    private final Settings settings = Settings.create()
            .set(Keys.INTEGER_MIN, 100)
            .set(Keys.INTEGER_MAX, 999);

    @Test
    void overridingSettings() {
        int x = Instancio.of(Integer.class)
                .withSettings(Settings.create()
                        .set(Keys.INTEGER_MIN, 1000)
                        .set(Keys.INTEGER_MAX, 9999))
                .create();

        assertThat(x).isBetween(1000, 9999);
    }
}

Configuration provided using withSettings(Settings) method has higher precedence than configuration from instancio.properties and @WithSettings. Therefore, in the above example x will be in the 1000..9999 range.