Quick Guide to EasyRandom in Java – Java中的EasyRandom快速指南

最后修改: 2019年 7月 12日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll show how to generate Java objects with the EasyRandom library.

在本教程中,我们将展示如何使用EasyRandom库生成Java对象。

2. EasyRandom

2.易拉罐

In some cases, we need a set of model objects that we’ll use for testing purposes. Or, we’d like to populate our test database with some data we’re going to make use of. Then, maybe we’d want to have collections of dummy DTOs to send back to our client.

在某些情况下,我们需要一组模型对象,我们将用于测试目的。或者,我们想用一些我们要利用的数据来填充我们的测试数据库。然后,也许我们想有一些假的DTO集合,以送回给我们的客户。

Setting up one, two or a few such objects might be easy if they’re not complex. Yet, there might be a case when we’d need hundreds of them immediately, without getting our hands dirty with manual setup.

设置一个、两个或几个这样的对象可能很容易,如果它们不复杂的话。然而,可能会有这样的情况,即我们立即需要数百个这样的对象,而不需要手动设置,弄脏我们的手。

Here’s where EasyRandom steps in. EasyRandom is a library that’s easy to use, requires little to nothing set up and just bypassing the class type, it’s gonna instantiate whole object graphs for us.

这里就是EasyRandom介入的地方。EasyRandom是一个库,它易于使用,几乎不需要任何设置,只要绕过类的类型,它就会为我们实例化整个对象图。

Let’s see how easy it is.

让我们看看这有多容易。

3. Maven Dependency

3.Maven的依赖性

First, let’s add the easy-random-core Maven dependency to our pom.xml:

首先,让我们把easy-random-core Maven依赖项添加到我们的pom.xml

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

4. Objects Generation

4.对象生成

The two most important classes in the library are:

图书馆中最重要的两个班级是。

  • EasyRandom that’s going to generate the objects, and
  • EasyRandomParameters that allows us to configure the generation process and make it more predictable.

4.1. Single Object

4.1.单一对象

Our first example generates a simple random Person object that has no nested objects, no collections, just an Integer, and two Strings.

我们的第一个例子生成了一个简单的随机Person对象,没有嵌套对象,没有集合,只有一个Integer和两个Strings

Let’s generate one instance of our object using nextObject(Class<T> t):

让我们使用nextObject(Class<T> t)生成我们对象的一个实例。

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

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

This is how the object might look after the generation:

这是该物体在生成后可能的样子。

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

As we can see, generated strings might be a bit too long, and age is negative. We’ll show how this can be tweaked in further sections.

我们可以看到,生成的字符串可能有点太长,而且年龄是负数。我们将在后面的章节中展示如何进行调整。

4.2. A Collection of Objects

4.2.一个对象的集合

Now, let’s say we need a collection of Person objects. Another method, objects(Class<T> t, int size) will allow us to do so.

现在,让我们假设我们需要一个Person对象的集合。另一个方法,objects(Class<T> t, int size)将允许我们这样做。

A nice thing is, it returns stream of objects, so eventually, we could add intermediate operations to it or group as we want.

很好的一点是,它返回对象流,所以最终,我们可以向它添加中间操作,或者按我们的要求分组。

Here’s how we could generate five instances of Person:

下面是我们如何生成五个Person的实例。

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

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

4.3. Complex Objects Generation

4.3.复杂对象的生成

Let’s have a look at our Employee class:

让我们看看我们的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;
}

Our class is relatively complex, it has a nested object, a collection, and a map.

我们的类相对复杂,它有一个嵌套对象,一个集合,和一个地图。

Now by default, the collection generation range is from 1 to 100, so our Collection<Employee> size would result in between.

现在默认情况下,集合的生成范围是1到100,所以我们的Collection<Employee>大小将导致在两者之间。

A good thing is, the objects are going to be cached and re-used, so not necessarily all are unique. Still, we might not need so many.

好在,这些对象将被缓存和重复使用,所以不一定都是唯一的。不过,我们可能不需要这么多。

We’ll soon take a look at how to adjust the collection’s range, but first, let’s see at another issue we might run into.

我们很快会看看如何调整集合的范围,但首先,让我们看看我们可能遇到的另一个问题。

In our domain, we have a YearQuarter class that represents a quarter of a year.

在我们的领域中,我们有一个YearQuarter类,代表一年中的一个季度。

There’s a bit of logic to set up the endDate to point exactly to 3 months after the start date:

有一点逻辑,设置endDate,精确地指向开始日期后的3个月

public class YearQuarter {

    private LocalDate startDate;
    private LocalDate endDate;

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

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

We must note, EasyRandom uses reflection to construct our objects, so generating this object through the library will result in data that, most likely, won’t be useful for us as our constraint of 3 months simply won’t be preserved.

我们必须注意,EasyRandom使用反射来构建我们的对象,所以通过库生成的这个对象将导致数据,很可能对我们没有用,因为我们3个月的约束根本不会被保留下来

Let’s have a look at how we could address this issue.

让我们来看看我们如何解决这个问题。

4.4. Generation Configuration

4.4.发电配置

In the below configuration, we supply our custom configuration via EasyRandomParameters.

在下面的配置中,我们通过EasyRandomParameters提供我们的定制配置。

First, we explicitly state our desired string length and collections size. Next, we exclude some of the fields from generation, let’s say we had a reason to have just nulls.

首先,我们明确说明我们希望的字符串长度和集合大小。接下来,我们排除一些字段的生成,比方说我们有理由只保留空字。

Here, we’ve used the handy FieldPredicates utility to chain the exclusion predicates.

在这里,我们使用了方便的FieldPredicates工具来连锁排他性谓词。

After that, we exclude everything from “not.existing.pkg” Java package, through another handy TypePredicates utility.

之后,我们通过另一个方便的TypePredicates工具,排除“not.existing.pkg”Java包中的一切。

And finally, as promised, we address the issue with startDate and endDate generation of YearQuarter class by applying our custom YearQuarterRandomizer:

最后,正如承诺的那样,我们通过应用我们自定义的YearQuarterRandomizer:来解决startDateendDate类的生成问题。

@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));
    }
}

5. Conclusion

5.总结

Manually setting up a model, DTO or entity objects might be cumbersome and result in less readable code and duplications. EasyRandom is a nice tool that can save time and help with it.

手动设置模型、DTO或实体对象可能会很麻烦,并导致代码的可读性较差和重复。EasyRandom是一个很好的工具,可以节省时间并提供帮助。

As we saw, the library doesn’t generate meaningful String objects, but there’s another tool called Java Faker with which we could create custom randomizers for the fields to sort it out as well.

正如我们所看到的,该库并没有生成有意义的String对象,但是还有一个工具叫做Java Faker,我们可以用它来为字段创建自定义的随机器,从而也能将其分类。

Also, to have a deeper view of the library and see how much more it can be configured, we might have a look at its Github Wiki page.

另外,为了更深入地了解这个库,看看它还能有多少配置,我们可以看看它的Github Wiki页面

As usual, the code can be found over the GitHub.

像往常一样,可以在GitHub上找到该代码。