1. Overview

在 Java 开发中,我们经常需要为测试或数据填充创建一些“假对象”。比如测试时需要构造一堆 DTO,或者初始化测试数据库的数据。如果手动一个个 new 出来,不仅效率低,而且代码冗长。

这时候就可以用到 EasyRandom 这个库。它是一个轻量级的对象生成工具,可以自动创建复杂对象图,无需手动初始化,简单粗暴。

本文将带你快速上手 EasyRandom 的基本使用和一些高级配置技巧。


2. Maven 依赖

使用前先在 pom.xml 中添加 EasyRandom 的核心依赖:

<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-random-core</artifactId>
    <version>4.0.0</version>
</dependency>

3. 对象生成基础

EasyRandom 的两个核心类:

  • EasyRandom:用于生成对象
  • EasyRandomParameters:用于配置生成行为

3.1 生成单个对象

我们先来看一个最简单的例子:生成一个 Person 对象。

@Test
void givenDefaultConfiguration_thenGenerateSingleObject() {
    EasyRandom generator = new EasyRandom();
    Person person = generator.nextObject(Person.class);

    assertNotNull(person.getAge());
    assertNotNull(person.getFirstName());
    assertNotNull(person.getLastName());
}

输出示例:

Person[firstName='eOMtThyhVNLWUZNRcBaQKxI', lastName='yedUsFwdkelQbxeTeQOvaScfqIOOmaa', age=-1188957731]

⚠️ 注意:默认生成的字符串较长,且年龄可能为负数。如果你对这些有要求,后面会教你怎么定制。

3.2 生成多个对象

如果你想一次生成多个对象,可以用 objects(Class<T>, int size) 方法:

@Test
void givenDefaultConfiguration_thenGenerateObjectsList() {
    EasyRandom generator = new EasyRandom();
    List<Person> persons = generator.objects(Person.class, 5)
        .collect(Collectors.toList());

    assertEquals(5, persons.size());
}

返回的是 Stream<T>,你可以加中间操作或做聚合处理。

3.3 生成复杂对象

考虑如下 Employee 类:

public class Employee {
    private long id;
    private String firstName;
    private String lastName;
    private Department department;
    private Collection<Employee> coworkers;
    private Map<YearQuarter, Grade> quarterGrades;
}

它包含嵌套对象、集合和 Map,结构相对复杂。默认情况下,EasyRandom 会自动处理这些结构:

  • 集合默认大小范围为 1~100
  • 生成的对象会被缓存复用(不是每个都唯一)

但有个问题:如果你的类中有一些业务逻辑(如构造函数里自动设置字段),EasyRandom 默认用反射生成对象,这些逻辑不会被触发。

比如下面这个 YearQuarter 类:

public class YearQuarter {

    private LocalDate startDate;
    private LocalDate endDate;

    public YearQuarter(LocalDate startDate) {
        this.startDate = startDate;
        autoAdjustEndDate();
    }

    private void autoAdjustEndDate() {
        endDate = startDate.plusMonths(3L);
    }
}

使用 EasyRandom 默认生成的 YearQuarter 对象,endDate 不会自动设置为 startDate 的三个月后。

怎么办?看下节。


4. 自定义配置

我们可以通过 EasyRandomParameters 来定制生成行为。

4.1 常见配置项

@Test
void givenCustomConfiguration_thenGenerateSingleEmployee() {
    EasyRandomParameters parameters = new EasyRandomParameters();
    parameters.stringLengthRange(3, 3);             // 限制字符串长度
    parameters.collectionSizeRange(5, 5);           // 限制集合大小
    parameters.excludeField(FieldPredicates.named("lastName").and(FieldPredicates.inClass(Employee.class))); // 排除某个字段
    parameters.excludeType(TypePredicates.inPackage("not.existing.pkg")); // 排除某个包下的类型
    parameters.randomize(YearQuarter.class, new YearQuarterRandomizer()); // 自定义随机器

    EasyRandom generator = new EasyRandom(parameters);
    Employee employee = generator.nextObject(Employee.class);

    assertEquals(3, employee.getFirstName().length());
    assertEquals(5, employee.getCoworkers().size());
    assertEquals(5, employee.getQuarterGrades().size());
    assertNotNull(employee.getDepartment());

    assertNull(employee.getLastName());

    for (YearQuarter key : employee.getQuarterGrades().keySet()) {
        assertEquals(key.getStartDate(), key.getEndDate().minusMonths(3L));
    }
}

4.2 自定义 Randomizer

上面的 YearQuarterRandomizer 是一个自定义的随机器,用于保证 startDateendDate 之间的关系正确。

你可以实现 Randomizer<T> 接口来定义自己的生成逻辑:

public class YearQuarterRandomizer implements Randomizer<YearQuarter> {
    @Override
    public YearQuarter getRandomValue() {
        LocalDate startDate = LocalDate.now().plusDays(new Random().nextInt(100));
        return new YearQuarter(startDate);
    }
}

5. 小结与建议

✅ EasyRandom 是一个非常实用的工具,能极大简化测试数据构造。
✅ 支持嵌套对象、集合、Map 等复杂结构。
✅ 可通过 EasyRandomParameters 做精细控制。
❌ 默认生成的字符串和数字可能不符合业务需求,需配合自定义 Randomizer 使用。
💡 如果你需要更真实的测试数据(比如中文姓名、手机号等),可以搭配 Java Faker 使用。

更多配置项和高级用法,可以参考其 GitHub Wiki

完整代码示例可在 GitHub 上找到。


原始标题:Quick Guide to EasyRandom in Java