共计 5554 个字符,预计需要花费 14 分钟才能阅读完成。
前言
在日常的测试中,咱们常常须要提前准备一大堆测试数据,用来验证业务逻辑。当然对于简略的数据类型齐全能够通过 JDK 自带的 Random
类来实现。然而对于一个比较复杂的类,或者参数的格局有特殊要求的时候,Random
就不实用了,这个时候就须要借助一些可能生成测试数据的框架。
相干框架
我在理论调研中,找到了 2 个在集体看来还不错的生成框架,他们别离是:
- jmockdata
- java-faker
上面我将一一介绍这些框架的优缺点以及实用场景。话不多说,间接开始撸代码。
JmockData
首先出场的是 JmockData 框架,它是官网定义如下:
一款实现模仿 JAVA 类型或对象的实例化并随机初始化对象的数据的工具框架。
依赖
<dependency>
<groupId>com.github.jsonzou</groupId>
<artifactId>jmockdata</artifactId>
<version>4.2.0</version>
</dependency>
根底类型数据生成
@Test
public void testBaseType(){
// 根底数据类型
System.out.println(JMockData.mock(byte.class));
System.out.println(JMockData.mock(int.class));
System.out.println(JMockData.mock(long.class));
System.out.println(JMockData.mock(double.class));
System.out.println(JMockData.mock(float.class));
System.out.println(JMockData.mock(String.class));
System.out.println(JMockData.mock(BigDecimal.class));
// 根底数据类型的数组
System.out.println(JMockData.mock(byte[].class));
System.out.println(JMockData.mock(int[].class));
System.out.println(JMockData.mock(long[].class));
System.out.println(JMockData.mock(double[].class));
System.out.println(JMockData.mock(float[].class));
System.out.println(JMockData.mock(String[].class));
System.out.println(JMockData.mock(BigDecimal[].class));
}
运行后果
0
2610
3401
8582.18
7194.44
5Xu7
9051.92
[B@7fbe847c
[I@41975e01
[J@c2e1f26
[D@dcf3e99
[F@6d9c638
[Ljava.lang.String;@7dc5e7b4
[Ljava.math.BigDecimal;@1ee0005
JavaBean 类型数据生成
/**
* java bean 测试
*/
@Test
public void testJavaBean(){Person mock = JMockData.mock(Person.class);
System.out.println(mock);
}
运行后果
Person[address=RrayfQIK,age=5863,idCard=SDn,name=j]
这里能够看到,应用 JMockdata.mock(xx.class);
能够很容易的生成一个 JavaBean。框架通过反射,在底层遍历取得类的属性与类型,而后填充数据。
然而与此同时,大家也发现了,尽管咱们能够的的确确的生成了一个 Person
类,也给它的每个属性都填充了值,然而生成的数据只是依据类型简略生成的,比方 age
字段被填充的是 5863。如果数据有事实含意,没有规定的随机就很容易呈现乌龙。
要解决这个问题,咱们就要限度随机数据的范畴,能够通过它的配置性能实现。
应用随机配置
@Test
public void testJavaBeanWithConfig() {
MockConfig mockConfig =
new MockConfig()
.subConfig("age")
// 设置 int 的范畴
.intRange(1, 100)
.subConfig("email")
// 设置生成邮箱正则
.stringRegex("[a-z0-9]{5,15}\\@\\w{3,5}\\.[a-z]{2,3}")
.globalConfig();
Person mock = JMockData.mock(Person.class, mockConfig);
System.out.println(mock);
}
运行后果
Person[address=hXttj2s,age=2,email=w14hnn@UvFB9.kt,idCard=V5bBdX,name=KM8]
能够看到 age
跟 email
曾经失常了,能够通过他弱小的配置性能对于数据进行生成的限度,然而你也发现了,对于一些有简略边界的数据,这样做能够,否则就像 address、name 这样的数据,很难通过简略规定去生成。
而对于有现实意义的数据生成,能够应用 java-faker 框架。
Java-faker
依赖
<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.2</version>
</dependency>
数据生成
@Test
public void testRandomName() {Faker faker = new Faker();
final Name name = faker.name();
System.out.println("firstName :" + name.firstName());
System.out.println("username :" + name.username());
System.out.println("bloodGroup :" + name.bloodGroup());
System.out.println("suffix :" + name.suffix());
System.out.println("title :" + name.title());
System.out.println("lastName :" + name.lastName());
System.out.println("nameWithMiddle :" + name.nameWithMiddle());
System.out.println("fullName :" + name.fullName());
System.out.println("name :" + name.name());
System.out.println("prefix :" + name.prefix());
}
生成后果
firstName : Hollis
username : cristy.white
bloodGroup : O-
suffix : Sr.
title : Product Implementation Specialist
lastName : Johnston
nameWithMiddle : Alesia Hagenes Kiehn
fullName : Dr. Pat Marvin
name : Ms. Jamal Rau
prefix : Mr.
能够看到 java-faker 生成数据特地的不便,根本格局如下:
Faker faker = new Faker();
final Xx xx = faker.xx();
xx.yyyy;
步骤:
- 创立 faker 对象
- 通过 faker 对象取得要生成的实体对象
- 调用实体对象取得对于生成的局部
这里的实体对象,对应下面的 name,也就说咱们要生成姓名相干的数据,拿到实体对象后还能够只取得其中的局部数据,比方姓名中的姓或名,还有前缀,甚至血型,能够说是十分全面。
而且 java-faker 反对的实体对象特地的多,如下:
- Address
- Ancient
- Animal
- App
- Aqua Teen Hunger Force
- Artist
- Avatar
- Back To The Future
- Aviation
- Basketball
- Beer
- Bojack Horseman
- Book
- Bool
- Business
- ChuckNorris
- Cat
- Code
- Coin
- Color
- Commerce
- Company
- Crypto
- DateAndTime
- Demographic
- Disease
- Dog
- DragonBall
- Dune
- Educator
- Esports
- File
- Finance
- Food
- Friends
- FunnyName
- GameOfThrones
- Gender
- Hacker
- HarryPotter
- Hipster
- HitchhikersGuideToTheGalaxy
- Hobbit
- HowIMetYourMother
- IdNumber
- Internet
- Job
- Kaamelott
- LeagueOfLegends
- Lebowski
- LordOfTheRings
- Lorem
- Matz
- Music
- Name
- Nation
- Number
- Options
- Overwatch
- PhoneNumber
- Pokemon
- Princess Bride
- Relationship Terms
- RickAndMorty
- Robin
- RockBand
- Shakespeare
- SlackEmoji
- Space
- StarTrek
- Stock
- Superhero
- Team
- TwinPeaks
- University
- Weather
- Witcher
- Yoda
- Zelda
从身份证到姓名再到地址、动物、书籍、头像、职位等等,基本上笼罩了咱们生存中的方方页面。
另外,java-faker 更贴心的是帮咱们实现了国际化,可能方才看了姓名的例子,有些敌人感觉这个框架难看但不好用,就拿生成姓名来说,生成都是 Johnston、Tom、Kiwi 之类英文名,在国内很少用到这些数据。其实 java-faker 曾经思考到这个问题。而且只有改一行代码就能够了。
批改后的代码
// 原代码 Faker faker = new Faker();
// 新代码
Faker faker = new Faker(Locale.CHINA);
final Name name = faker.name();
System.out.println("firstName :" + name.firstName());
System.out.println("username :" + name.username());
System.out.println("bloodGroup :" + name.bloodGroup());
System.out.println("suffix :" + name.suffix());
System.out.println("title :" + name.title());
System.out.println("lastName :" + name.lastName());
System.out.println("nameWithMiddle :" + name.nameWithMiddle());
System.out.println("fullName :" + name.fullName());
System.out.println("name :" + name.name());
System.out.println("prefix :" + name.prefix());
生成后果
firstName : 熠彤
username : 烨霖. 龙
bloodGroup : A-
suffix : IV
title : Investor Division Engineer
lastName : 范
nameWithMiddle : 胡思
fullName : 孟鸿涛
name : 黎航
prefix : Miss
只须要,把之前的 Faker faker = new Faker(); 改成 Faker faker = new Faker(Locale.CHINA); 即可。如果你想生成其它国家的内容也是能够的,java-faker 反对的国家如下:
- bg
- ca
- ca-CAT
- da-DK
- de
- de-AT
- de-CH
- en
- en-AU
- en-au-ocker
- en-BORK
- en-CA
- en-GB
- en-IND
- en-MS
- en-NEP
- en-NG
- en-NZ
- en-PAK
- en-SG
- en-UG
- en-US
- en-ZA
- es
- es-MX
- fa
- fi-FI
- fr
- he
- hu
- in-ID
- it
- ja
- ko
- nb-NO
- nl
- pl
- pt
- pt-BR
- ru
- sk
- sv
- sv-SE
- tr
- uk
- vi
- zh-CN
- zh-TW
总结
JmockData
个人感觉它是 plus 版的 Random 类,不便简略的按类型生成数据,也能够本人给定配置与规定去生成,毛病,上文也说了,生成的数据没有太多实际意义,简略数据还好,如果像姓名、地址等有现实意义的数据,就不太适合了。
Java-faker
java-faker 其实是迁徙自 ruby 中赫赫有名的 faker。很多语言都有他的对应迁徙,比方 python、java。所以数据量和性能是很欠缺并且通过考验的,应用起来也很不便。理论工作中,能够优化应用。如果要说毛病,集体感觉他有些中央国际化的并不全面,比方车牌、身份证之类的。如果对于这些数据有比拟严格的要求,举荐另一个我的项目 yindz/common-random: 简略易用的随机数据生成器。这个我的项目对于本地化数据,做了很多解决,根本够用。