• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

测试 Java优雅的生成测试数据

武飞扬头像
等风来.长
帮助1

前言


在日常的测试中,我们经常需要提前准备一大堆测试数据,用来验证业务逻辑。当然对于简单的数据类型完全可以通过 JDK 自带的 Random 类来实现。但是对于一个比较复杂的类,或者参数的格式有特殊要求的时候,Random 就不适用了,这个时候就需要借助一些能够生成测试数据的框架。

相关框架


我在实际调研中,找到了 2 个在个人看来还不错的生成框架,他们分别是:

  1. jmockdata[1]

  2. java-faker[2]


下面我将一个一个地介绍这些框架的优缺点以及适用场景。话不多说,直接开始撸代码。

JmockData


首先出场的是 JmockData 框架,它是官方定义如下:

一款实现模拟JAVA类型或对象的实例化并随机初始化对象的数据的工具框架。

依赖

  1.  
      <dependency>
  2.  
         <groupId>com.github.jsonzou</groupId>
  3.  
         <artifactId>jmockdata</artifactId>
  4.  
         <version>4.2.0</version>
  5.  
       </dependency>

基础类型数据生成

  1.  
        @Test
  2.  
        public void testBaseType(){
  3.  
            // 基础数据类型
  4.  
            System.out.println(JMockData.mock(byte.class));
  5.  
            System.out.println(JMockData.mock(int.class));
  6.  
            System.out.println(JMockData.mock(long.class));
  7.  
            System.out.println(JMockData.mock(double.class));
  8.  
            System.out.println(JMockData.mock(float.class));
  9.  
            System.out.println(JMockData.mock(String.class));
  10.  
            System.out.println(JMockData.mock(BigDecimal.class));
  11.  
     
  12.  
            // 基础数据类型的数组
  13.  
            System.out.println(JMockData.mock(byte[].class));
  14.  
            System.out.println(JMockData.mock(int[].class));
  15.  
            System.out.println(JMockData.mock(long[].class));
  16.  
            System.out.println(JMockData.mock(double[].class));
  17.  
            System.out.println(JMockData.mock(float[].class));
  18.  
            System.out.println(JMockData.mock(String[].class));
  19.  
            System.out.println(JMockData.mock(BigDecimal[].class));
  20.  
        }
学新通

运行结果

  1.  
    0
  2.  
    2610
  3.  
    3401
  4.  
    8582.18
  5.  
    7194.44
  6.  
    5Xu7
  7.  
    9051.92
  8.  
    [B@7fbe847c
  9.  
    [I@41975e01
  10.  
    [J@c2e1f26
  11.  
    [D@dcf3e99
  12.  
    [F@6d9c638
  13.  
    [Ljava.lang.String;@7dc5e7b4
  14.  
    [Ljava.math.BigDecimal;@1ee0005

JavaBean 类型数据生成

  1.  
        /**
  2.  
         * java bean 测试
  3.  
         */
  4.  
        @Test
  5.  
        public void testJavaBean(){
  6.  
            Person mock = JMockData.mock(Person.class);
  7.  
            System.out.println(mock);
  8.  
        }

运行结果

Person[address=RrayfQIK,age=5863,idCard=SDn,name=j]


这里可以看到,使用 JMockdata.mock(xx.class); 可以很容易的生成一个 JavaBean。框架通过反射,在底层遍历获得类的属性与类型,然后填充数据。

但是与此同时,大家也发现了,虽然我们可以的的确确的生成了一个 Person 类,也给它的每个属性都填充了值,但是生成的数据只是根据类型简单生成的,比如 age 字段被填充的是 5863。如果数据有现实含义,没有规则的随机就很容易出现乌龙。

要解决这个问题,我们就要限制随机数据的范围,可以通过它的配置功能实现。

使用随机配置

  1.  
        @Test
  2.  
        public void testJavaBeanWithConfig() {
  3.  
     
  4.  
            MockConfig mockConfig =
  5.  
                    new MockConfig()
  6.  
                            .subConfig("age")
  7.  
                            // 设置 int 的范围
  8.  
                            .intRange(1100)
  9.  
                            .subConfig("email")
  10.  
                            // 设置生成邮箱正则
  11.  
                            .stringRegex("[a-z0-9]{5,15}\\@\\w{3,5}\\.[a-z]{2,3}")
  12.  
                            .globalConfig();
  13.  
     
  14.  
            Person mock = JMockData.mock(Person.class, mockConfig);
  15.  
            System.out.println(mock);
  16.  
        }
学新通

运行结果

Person[address=hXttj2s,age=2,email=w14hnn@UvFB9.kt,idCard=V5bBdX,name=KM8]


可以看到 age 跟 email 已经正常了,可以通过他强大的配置功能对于数据进行生成的限制,但是你也发现了,对于一些有简单边界的数据,这样做可以,否则就像 address 、 name 这样的数据,很难通过简单规则去生成。

而对于有现实意义的数据生成,可以使用 java-faker 框架。

Java-faker

依赖

  1.  
    <dependency>
  2.  
        <groupId>com.github.javafaker</groupId>
  3.  
        <artifactId>javafaker</artifactId>
  4.  
        <version>1.0.2</version>
  5.  
    </dependency>

数据生成

  1.  
        @Test
  2.  
        public void testRandomName() {
  3.  
            Faker faker = new Faker();
  4.  
            final Name name = faker.name();
  5.  
            System.out.println("firstName : "   name.firstName());
  6.  
            System.out.println("username : "   name.username());
  7.  
            System.out.println("bloodGroup : "   name.bloodGroup());
  8.  
            System.out.println("suffix : "   name.suffix());
  9.  
            System.out.println("title : "   name.title());
  10.  
            System.out.println("lastName : "   name.lastName());
  11.  
            System.out.println("nameWithMiddle : "   name.nameWithMiddle());
  12.  
            System.out.println("fullName : "   name.fullName());
  13.  
            System.out.println("name : "   name.name());
  14.  
            System.out.println("prefix : "   name.prefix());
  15.  
        }
学新通

生成结果

  1.  
    firstName : Hollis
  2.  
    username : cristy.white
  3.  
    bloodGroup : O-
  4.  
    suffix : Sr.
  5.  
    title : Product Implementation Specialist
  6.  
    lastName : Johnston
  7.  
    nameWithMiddle : Alesia Hagenes Kiehn
  8.  
    fullName : Dr. Pat Marvin
  9.  
    name : Ms. Jamal Rau
  10.  
    prefix : Mr.


可以看到 java-faker 生成数据特别的方便,基本格式如下:

  1.  
            Faker faker = new Faker();
  2.  
            final Xx xx = faker.xx();
  3.  
      xx.yyyy;


步骤:

  1. 创建 faker 对象

  2. 通过 faker 对象获得要生成的实体对象

  3. 调用实体对象获得对于生成的部分


这里的实体对象,对应上面的 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 已经考虑到这个问题。而且只要改一行代码就可以了。

修改后的代码

  1.  
      // 原代码 Faker faker = new Faker();
  2.  
      // 新代码
  3.  
            Faker faker = new Faker(Locale.CHINA);
  4.  
            final Name name = faker.name();
  5.  
            System.out.println("firstName : "   name.firstName());
  6.  
            System.out.println("username : "   name.username());
  7.  
            System.out.println("bloodGroup : "   name.bloodGroup());
  8.  
            System.out.println("suffix : "   name.suffix());
  9.  
            System.out.println("title : "   name.title());
  10.  
            System.out.println("lastName : "   name.lastName());
  11.  
            System.out.println("nameWithMiddle : "   name.nameWithMiddle());
  12.  
            System.out.println("fullName : "   name.fullName());
  13.  
            System.out.println("name : "   name.name());
  14.  
            System.out.println("prefix : "   name.prefix());

生成结果

  1.  
    firstName : 熠彤
  2.  
    username : 烨霖.龙
  3.  
    bloodGroup : A-
  4.  
    suffix : IV
  5.  
    title : Investor Division Engineer
  6.  
    lastName : 范
  7.  
    nameWithMiddle : 胡思
  8.  
    fullName : 孟鸿涛
  9.  
    name : 黎航
  10.  
    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: 简单易用的随机数据生成器。[3]这个项目对于本地化数据,做了很多处理,基本够用。

学习更多JAVA知识与技巧,关注与私信博主(555)!
热爱学习和渴望进阶的小伙伴,各种JAVA学习路线、笔记、面试题,免费分享!

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgakfhh
系列文章
更多 icon
同类精品
更多 icon
继续加载