截至 2020 年 11 月 15 日,Easy Random 处于维护模式。这意味着从现在开始只会解决错误修复(记录支持除外,该支持将在 Java 16 发布时发布)。目前仅支持版本 5.0.x(基于 Java 11)和版本 4.3.x(基于 Java 8)。请考虑尽早升级到这些版本之一。
Easy Random 是一个生成随机 Java 对象的库。您可以将其视为 JVM 的 ObjectMother。假设您有一个Person
类,并且您想要生成它的随机实例,我们开始吧:
EasyRandom easyRandom = new EasyRandom ();
Person person = easyRandom . nextObject ( Person . class );
EasyRandom#nextObject
方法能够生成任何给定类型的随机实例。
java.util.Random
API 提供了 7 种生成随机数据的方法: nextInt()
、 nextLong()
、 nextDouble()
、 nextFloat()
、 nextBytes()
、 nextBoolean()
和nextGaussian()
。如果你需要生成一个随机String
怎么办?或者说你的域对象的随机实例? Easy Random 提供了EasyRandom
API,它使用名为nextObject(Class type)
的方法扩展了java.util.Random
。该方法能够生成任意 Java bean 的随机实例。
EasyRandomParameters
类是配置EasyRandom
实例的主要入口点。它允许您设置所有参数来控制随机数据的生成方式:
EasyRandomParameters parameters = new EasyRandomParameters ()
. seed ( 123L )
. objectPoolSize ( 100 )
. randomizationDepth ( 3 )
. charset ( forName ( "UTF-8" ))
. timeRange ( nine , five )
. dateRange ( today , tomorrow )
. stringLengthRange ( 5 , 50 )
. collectionSizeRange ( 1 , 10 )
. scanClasspathForConcreteTypes ( true )
. overrideDefaultInitialization ( false )
. ignoreRandomizationErrors ( true );
EasyRandom easyRandom = new EasyRandom ( parameters );
有关这些参数的更多详细信息,请参阅配置参数部分。
在大多数情况下,默认选项就足够了,您可以使用EasyRandom
的默认构造函数。
Easy Random 允许您控制如何通过org.jeasy.random.api.Randomizer
接口生成随机数据,并可以使用java.util.function.Predicate
轻松从对象图中排除某些字段:
EasyRandomParameters parameters = new EasyRandomParameters ()
. randomize ( String . class , () -> "foo" )
. excludeField ( named ( "age" ). and ( ofType ( Integer . class )). and ( inClass ( Person . class )));
EasyRandom easyRandom = new EasyRandom ( parameters );
Person person = easyRandom . nextObject ( Person . class );
在前面的示例中,Easy Random 将:
String
类型的所有字段设置为foo
(使用定义为 lambda 表达式的Randomizer
)Person
中名为age
的Integer
类型字段。 named
、 ofType
和inClass
静态方法在org.jeasy.random.FieldPredicates
中定义,它提供了通用谓词,您可以组合使用来准确定义要排除的字段。名为TypePredicates
的类似类可用于定义要从对象图中排除的类型。您当然可以将自己的java.util.function.Predicate
与那些预定义的谓词结合使用。
用随机数据填充 Java 对象乍一看似乎很容易,除非您的域模型涉及许多相关的类。在前面的示例中,假设Person
类型定义如下:
如果没有Easy Random,您将编写以下代码来创建Person
类的实例:
Street street = new Street ( 12 , ( byte ) 1 , "Oxford street" );
Address address = new Address ( street , "123456" , "London" , "United Kingdom" );
Person person = new Person ( "Foo" , "Bar" , "[email protected]" , Gender . MALE , address );
如果这些类不提供带参数的构造函数(可能是一些您无法更改的遗留类型),您可以编写:
Street street = new Street ();
street . setNumber ( 12 );
street . setType (( byte ) 1 );
street . setName ( "Oxford street" );
Address address = new Address ();
address . setStreet ( street );
address . setZipCode ( "123456" );
address . setCity ( "London" );
address . setCountry ( "United Kingdom" );
Person person = new Person ();
person . setFirstName ( "Foo" );
person . setLastName ( "Bar" );
person . setEmail ( "[email protected]" );
person . setGender ( Gender . MALE );
person . setAddress ( address );
使用Easy Random,可以使用new EasyRandom().nextObject(Person.class)
生成随机Person
对象。该库将递归地填充所有对象图。这是一个很大的区别!
有时,测试夹具对于测试逻辑来说并不重要。例如,如果我们想测试新排序算法的结果,我们可以生成随机输入数据并断言输出已排序,而不管数据本身:
@ org . junit . Test
public void testSortAlgorithm () {
// Given
int [] ints = easyRandom . nextObject ( int []. class );
// When
int [] sortedInts = myAwesomeSortAlgo . sort ( ints );
// Then
assertThat ( sortedInts ). isSorted (); // fake assertion
}
另一个例子是测试域对象的持久性,我们可以生成一个随机域对象,将其持久化并断言数据库包含相同的值:
@ org . junit . Test
public void testPersistPerson () throws Exception {
// Given
Person person = easyRandom . nextObject ( Person . class );
// When
personDao . persist ( person );
// Then
assertThat ( "person_table" ). column ( "name" ). value (). isEqualTo ( person . getName ()); // assretj db
}
Easy Random 在许多其他用例中也很有用,您可以在 wiki 中找到一个非详尽的列表。
欢迎您通过 GitHub 上的拉取请求为该项目做出贡献。请注意,Easy Random 处于维护模式,这意味着只会考虑错误修复的拉取请求。
如果您认为发现了错误或有任何疑问,请使用问题跟踪器。
感谢大家的贡献!
麻省理工学院许可证。请参阅 LICENSE.txt。