Перейти к основному содержимому

Краткое руководство по EasyRandom в Java

· 5 мин. чтения

Задача: Наибольшая подстрока без повторений

Для заданной строки s, найдите длину наибольшей подстроки без повторяющихся символов. Подстрока — это непрерывная непустая последовательность символов внутри строки...

ANDROMEDA 42

1. Обзор

В этом руководстве мы покажем, как создавать объекты Java с помощью библиотеки EasyRandom .

2. EasyRandom

В некоторых случаях нам нужен набор объектов модели, которые мы будем использовать для целей тестирования. Или мы хотели бы заполнить нашу тестовую базу данных некоторыми данными, которые мы собираемся использовать. Затем, возможно, мы захотим иметь коллекции фиктивных DTO для отправки обратно нашему клиенту.

Настройка одного, двух или нескольких таких объектов может быть легкой, если они не сложные. Тем не менее, может быть случай, когда нам понадобятся сотни из них сразу, не пачкая рук ручной настройкой.

Здесь в дело вступает EasyRandom . EasyRandom — это библиотека, которую легко использовать, она практически ничего не требует настройки и, просто минуя тип класса, создает для нас экземпляры целых графов объектов.

Давайте посмотрим, насколько это легко.

3. Зависимость от Maven

Во-первых, давайте добавим зависимость Maven easy-random-core к нашему pom.xml :

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

4. Генерация объектов

Два наиболее важных класса в библиотеке:

  • EasyRandom , который будет генерировать объекты, и
  • EasyRandomParameters , который позволяет настроить процесс генерации и сделать его более предсказуемым.

4.1. Один объект

В нашем первом примере генерируется простой случайный объект Person , который не имеет ни вложенных объектов, ни коллекций, а только Integer и две строки String .

Давайте сгенерируем один экземпляр нашего объекта, используя 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());
}

Вот как объект может выглядеть после генерации:

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

Как мы видим, сгенерированные строки могут быть слишком длинными, а возраст — отрицательным. Мы покажем, как это можно настроить в следующих разделах.

4.2. Коллекция объектов

Теперь предположим, что нам нужна коллекция объектов Person . Другой метод, objects(Class<T> t, int size) позволит нам сделать это.

Приятно то, что он возвращает поток объектов, поэтому в конечном итоге мы можем добавить к нему промежуточные операции или сгруппировать, как захотим.

Вот как мы можем сгенерировать пять экземпляров 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. Генерация сложных объектов

Давайте посмотрим на наш класс 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;
}

Наш класс относительно сложен, у него есть вложенный объект, коллекция и карта.

Теперь по умолчанию диапазон генерации коллекции составляет от 1 до 100 , поэтому размер нашей коллекции<Employee> будет между ними.

Хорошо, что объекты будут кэшироваться и повторно использоваться , поэтому не обязательно все они будут уникальными. Тем не менее, нам может не понадобиться так много.

Вскоре мы рассмотрим, как настроить диапазон коллекции, но сначала давайте посмотрим на другую проблему, с которой мы можем столкнуться.

В нашем домене у нас есть класс YearQuarter , представляющий квартал года.

Есть немного логики, чтобы настроить 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);
}
}

Надо отметить, что EasyRandom использует рефлексию для построения наших объектов , поэтому генерация этого объекта через библиотеку приведет к получению данных, которые, скорее всего, нам не пригодятся, так как наше ограничение в 3 месяца просто не сохранится .

Давайте посмотрим, как мы могли бы решить эту проблему.

4.4. Конфигурация генерации

В приведенной ниже конфигурации мы предоставляем нашу пользовательскую конфигурацию через EasyRandomParameters .

Во-первых, мы явно указываем желаемую длину строки и размер коллекций. Далее мы исключаем часть полей из генерации, допустим, у нас была причина иметь только нули.

Здесь мы использовали удобную утилиту FieldPredicates для объединения предикатов исключения.

После этого исключаем все из Java-пакета «not.existing.pkg» , через еще одну удобную утилиту TypePredicates .

И, наконец, как и было обещано, мы решаем проблему с генерацией startDate и endDate класса YearQuarter , применяя наш собственный YearQuarterRandomizer:

@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. Вывод

Ручная настройка модели, DTO или объектов сущности может быть громоздкой и привести к менее читаемому коду и дублированию. EasyRandom — хороший инструмент, который может сэкономить время и помочь с ним.

Как мы видели, библиотека не генерирует осмысленных объектов String , но есть еще один инструмент под названием Java Faker , с помощью которого мы можем создавать собственные рандомизаторы для полей, чтобы также их сортировать.

Кроме того, чтобы получить более глубокое представление о библиотеке и увидеть, насколько больше ее можно настроить, мы могли бы заглянуть на ее страницу Github Wiki .

Как обычно, код можно найти на GitHub .