介绍

前后端分离项目,前端和后端人员都是根据 API 文档进行开发项目的,不应该直接相互依赖, 前端人员不应该等待后端开发好接口后再进行测试,既然不依赖后端接口,那前端人员应该如何测试呢?

可以通过模拟数据生成器,通过一定规则 (API文档)生成模拟数据接口, 提供给前端人员进行测试。

官网:http://mockjs.com/

文档:https://github.com/nuysoft/Mock/wiki

Mock.js 是用于生成随机数据,拦截 Ajax 请求。通过拦截 Ajax 请求,根据数据模板生成并返回模拟数据,让前端攻城师独立于后端进行开发,帮助编写单元测试。

Mock.js 作用:

  • 前后端分离:让前端攻城师独立于后端进行开发。
  • 增加单元测试的真实性:通过随机数据,模拟各种场景。
  • 开发无侵入:不需要修改既有代码,就可以拦截 Ajax 请求,返回模拟的响应数据。
  • 用法简单
  • 数据类型丰富:支持生成随机的文本、数字、布尔值、日期、邮箱、链接、图片、颜色等。
  • 方便扩展:支持扩展更多数据类型,支持自定义函数和正则。
安装
npm install mockjs

简单使用

需求:生成 6 条列表数据。

创建一个mock.js的文件,写入如下代码

const Mock = require('mockjs')  // 导入mock
const data = Mock.mock({
// 定义数据生成规则
'memberList|6': [ // 管道符|后面的6表示生成6条数据
{
'id':1,
'name': '邹邹'
}
]
})
console.log(data) // 打印数据

这样写浏览器无法帮我们解析,可以在mock.js目录下执行node mock.js

Vue--MockJs_数据

 我们也可以让格式化后显示,更改最后一行

const Mock = require('mockjs')  // 导入mock
const data = Mock.mock({
// 定义数据生成规则
'memberList|6': [ // 管道符|后面的6表示生成6条数据
{
'id':1,
'name': '邹邹'
}
]
})
console.log( JSON.stringify(data, null, 2)) // stringfy(数据,数据转换函数,缩进空格数)

Vue--MockJs_数据_02

上面生成的4条数据是一样的,如果希望它按一定规律生成随机数据,就需要按 Mock.js 的语法规范来定义。

Mock.js 的语法规范包括两部分:

  • 1. 数据模板定义规范(Data Template Definition,DTD)
  • 2. 数据占位符定义规范(Data Placeholder Definition,DPD)

数据模板定义规范 DTD

 数据模版中的每个属性 由三部分构成:属性名,生成规则,属性值。

// '属性名|生成规则': 属性值

注意:

  • 属性名和生成规则之间用管道符 | 分割。
  • 生成规则是可选的,生成规则有7种格式
'name|min-max': value
'name|count': value
'name|min-max.dmin-dmax': value
'name|min-max.dcount': value
'name|count.dmin-dmax': value
'name|count.dcount': value
'name|+step': value

生成规则 的 含义 需要依赖 属性值的类型 才能确定。

属性值 中可以含有  @占位符 。属性值 指定了最终值的初始值和类型。

属性值是字符串 String

1. 'name|count': string

通过重复 string 生成一个字符串,重复次数等于 count 。

2. 'name|min-max': string

通过重复 string 生成一个字符串,重复次数大于等于 min ,小于等于 max 。

属性值是数字 Number

1. 'name|+1': number

属性值自动加 1,初始值为 number 。

2. 'name|min-max': number

生成一个大于等于 min 、小于等于 max 的整数,属性值 number 只是用来确定类型。

3. 'name|min-max.dmin-dmax': number

生成一个浮点数,整数部分大于等于 min 、小于等于 max ,小数部分保留 dmin 到 dmax 位。

属性值是布尔型 Boolean

1. 'name|1': boolean

随机生成一个布尔值,值为 true 的概率是 1/2,值为 false 的概率同样是 1/2。

2. 'name|min-max': value

随机生成一个布尔值,值为 value 的概率是 min / (min + max) ,值为 !value 的概率是 max / (min + max) 。

属性值是对象 Object

1. 'name|count': object

从属性值 object 中随机选取 count 个属性。

2. 'name|min-max': object

从属性值 object 中随机选取 min 到 max 个属性。

属性值是数组 Array

1. 'name|min-max': array

通过重复属性值 array 生成一个新数组,重复次数大于等于 min ,小于等于 max 。

2. 'name|count': array

通过重复属性值 array 生成一个新数组,重复次数为 count 。

属性值是正则表达式 RegExp

. 'name': regexp

根据正则表达式 regexp 反向生成可以匹配它的字符串。用于生成自定义格式的字符串。

注意 regexp 是没有引号的

const Mock = require('mockjs')  // 导入mock
const data = Mock.mock({
// 定义数据生成规则
'memberList|6': [ // 管道符|后面的6表示生成6条数据
{
'id|+1':2, // 自增长1,初始值为2
'name|1-3': '邹邹', // 随机生成1-3个重叠邹邹
'job|2': 'IT', // 生成两个IT
'age|1-120': 1, // 随机生成1-120之间的整数
'salary|6000-8000.1-3':1 , // 随机生成6000到8000之间的数字,并且小数部分是1到三位,后面的1只是说明是number型
'status|1': true, // 随机生成true或false,并且概率都是1/2
'open|2-4':false, // 生成的概率。true的概率为4/(2+4),false的概率2(2+4)
'order|2':{id:1,name:'小微',age:18}, // 在对象中随机生成两个属性进行返回
'orde2|2-3':{id:1,name:'小微',age:18}, // 在对象中随机生成两个或三个属性进行返回
'idCard': /\d{15}|\d{18}/ // 指定正则表达式,当前生成省份证号,注意,不要用单引号引起来
}
]
})
console.log( JSON.stringify(data, null, 2)) // 打印数据

Vue--MockJs_数据_03

Vue--MockJs_属性值_04

{
"memberList": [
{
"id": 2,
"name": "邹邹邹邹",
"job": "ITIT",
"age": 120,
"salary": 6507.56,
"status": true,
"open": true,
"order": {
"name": "小微",
"age": 18
},
"orde2": {
"name": "小微",
"age": 18,
"id": 1
},
"idCard": "019559495798340"
},
{
"id": 3,
"name": "邹邹",
"job": "ITIT",
"age": 112,
"salary": 6911.3,
"status": false,
"open": false,
"order": {
"name": "小微",
"age": 18
},
"orde2": {
"name": "小微",
"age": 18
},
"idCard": "363103436670144776"
},
{
"id": 4,
"name": "邹邹邹邹",
"job": "ITIT",
"age": 89,
"salary": 7028.76,
"status": false,
"open": false,
"order": {
"age": 18,
"name": "小微"
},
"orde2": {
"age": 18,
"name": "小微"
},
"idCard": "484071382771567"
},
{
"id": 5,
"name": "邹邹邹邹",
"job": "ITIT",
"age": 39,
"salary": 6427.85,
"status": true,
"open": true,
"order": {
"name": "小微",
"age": 18
},
"orde2": {
"age": 18,
"id": 1
},
"idCard": "946240463874191"
},
{
"id": 6,
"name": "邹邹",
"job": "ITIT",
"age": 65,
"salary": 7635.88,
"status": false,
"open": true,
"order": {
"name": "小微",
"id": 1
},
"orde2": {
"age": 18,
"name": "小微",
"id": 1
},
"idCard": "241267827845265523"
},
{
"id": 7,
"name": "邹邹邹邹",
"job": "ITIT",
"age": 99,
"salary": 6071.23,
"status": true,
"open": false,
"order": {
"age": 18,
"id": 1
},
"orde2": {
"name": "小微",
"id": 1,
"age": 18
},
"idCard": "122687462329326"
}
]
}

生成的结果

数据占位符定义规范 DPD

Mock.Random 是一个工具类,用于生成各种随机数据。

Mock.Random 类中的方法在数据模板中称为『占位符』,书写格式为 @占位符(参数 [, 参数]) 。

占位符 的格式为:

'属性名': @占位符

Mock.Random 类中提供的完整方法(占位符)如下:

Type(类型)           Method(占位符)
Basic boolean , natural (自然数,大于等于 0 的整数), integer , float , character , string ,range (整型数组),
Date date (年月日), time (时分秒), datetime (年月日时分秒)
Image image, dataImage
Color color
Text paragraph, sentence, word, title, cparagraph, csentence, cword, ctitle
Name first, last, name, cfirst, clast, cname
Web url, domain, email, ip, tld
Address area, region
Helper capitalize, upper, lower, pick, shuffle
Miscellaneous guid, id
基本类型占位符

随机生成基本数据类型的数据。

常用的占位符:natural/integer/string/float/boolean

const Mock = require('mockjs')  // 导入mock
const data = Mock.mock({
// 定义数据生成规则
'empList|3': [{
'id|+1': 1, // 每次递增1
'name': '@string', // 随机生成字符串
'price': '@float', // 随机生成浮点数
'status': '@boolean', // 随机生成布尔值
}]

})
console.log(JSON.stringify(data, null, 2)) // 打印数据

Vue--MockJs_数据_03

Vue--MockJs_属性值_04

{
"empList": [
{
"id": 1,
"name": "73Yj",
"price": -3909608004187152,
"status": true
},
{
"id": 2,
"name": "%ZlpU7^",
"price": -3646675443094164,
"status": true
},
{
"id": 3,
"name": "BRVD",
"price": 2207781483963188.8,
"status": false
}
]
}

结果

日期占位符

随机生成日期类型的数据,

占位符:

  • date/date(format)
  • time/time(format)
  • datetime/datetime(format)
const Mock = require('mockjs')  // 导入mock
const data = Mock.mock({
// 定义数据生成规则
'empList|3': [{
'birthday': '@date', // 默认 yyyy-MM-dd
'entryDate': '@date("yyyy/MM/dd")', // 指定日期格式 yyyy/MM/dd
'createDate': '@datetime', // 默认 yyyy-MM-dd HH:mm:ss
'updateDate': '@datetime("yyyy/MM/dd HH:mm:ss")' //默认yyyy/MM/dd HH:mm:ss
}]

})
console.log(JSON.stringify(data, null, 2)) // 打印数据

Vue--MockJs_数据_03

Vue--MockJs_属性值_04

{
"empList": [
{
"birthday": "1980-04-30",
"entryDate": "2009/01/09",
"createDate": "1988-11-10 12:25:05",
"updateDate": "1999/10/23 13:05:30"
},
{
"birthday": "1989-04-30",
"entryDate": "1987/01/07",
"createDate": "2005-02-05 20:52:51",
"updateDate": "1980/11/01 05:12:25"
},
{
"birthday": "2001-11-06",
"entryDate": "2010/12/16",
"createDate": "2016-09-13 04:53:26",
"updateDate": "1972/10/13 14:11:21"
}
]
}

结果

图像占位符

随机生成图片地址, 生成的浏览器可以打开

占位符: image

const Mock = require('mockjs')  // 导入mock
const data = Mock.mock({
// 定义数据生成规则
'empList|3': [{
'pic': '@image',
}]

})
console.log(JSON.stringify(data, null, 2)) // 打印数据

Vue--MockJs_数据_03

Vue--MockJs_属性值_04

{
"empList": [
{
"pic": "http://dummyimage.com/468x60"
},
{
"pic": "http://dummyimage.com/250x250"
},
{
"pic": "http://dummyimage.com/120x240"
}
]
}

结果

文本占位符

随机生成一段文本

占位符:

ctitle 随机生成一句中文标题。

csentence(mix, max) 随机生成一段中文文本。

const Mock = require('mockjs')  // 导入mock
const data = Mock.mock({
// 定义数据生成规则
'empList|3': [{
'title': '@ctitle(3, 6)', // 中文标题(3到6个字)
'content': '@csentence(8, 12)', // 一段中文文本(8到12个字)
}]

})
console.log(JSON.stringify(data, null, 2)) // 打印数据

Vue--MockJs_数据_03

Vue--MockJs_属性值_04

{
"empList": [
{
"title": "本接王提进",
"content": "里斗王支总江们平青。"
},
{
"title": "油我然理",
"content": "按美华并工马片种际。"
},
{
"title": "色里增县",
"content": "色劳受周争律计气派革程记。"
}
]
}

结果

名称占位符

随机生成名称。
占位符:

  • first 英文名。
  • last 英文姓。
  • name 英文姓名。
  • cfirst 中文名。
  • clast 中文姓。
  • cname 中文姓名。
const Mock = require('mockjs')  // 导入mock
const data = Mock.mock({
// 定义数据生成规则
'empList|3': [{
'first': '@cfirst', // 中文名
'last': '@last', // 英文姓
'name': '@cname', // 中文名
}]

})
console.log(JSON.stringify(data, null, 2)) // 打印数据
{
"empList": [
{
"first": "朱",
"last": "Lee",
"name": "于明"
},
{
"first": "魏",
"last": "Martin",
"name": "石杰"
},
{
"first": "王",
"last": "Thomas",
"name": "邱平"
}
]
}
网络占位符

可随机生成 URL 、域名、 IP 地址、邮件地址

占位符:

url(protocol, host) 生成 URL。

  • protocol: 协议, 如 http
  • host:域名和端口号,如 zouzou.com
const Mock = require('mockjs')  // 导入mock
const data = Mock.mock({
// 定义数据生成规则
'empList|3': [{
'url': '@url("http", "zouzou.com")', // URL
'domain': '@domain', // 域名
'ip': '@ip', // IP
'email': '@email' // 邮箱地址
}]

})
console.log(JSON.stringify(data, null, 2)) // 打印数据

Vue--MockJs_数据_03

Vue--MockJs_属性值_04

{
"empList": [
{
"url": "http://zouzou.com/rdfcvsf",
"domain": "dnkcrees.ao",
"ip": "247.161.170.44",
"email": "r.yakh@eweochokms.cf"
},
{
"url": "http://zouzou.com/jkgd",
"domain": "tqxkv.pa",
"ip": "111.234.9.42",
"email": "k.roazrdxma@wfbvkvtubc.中国互联.网络"
},
{
"url": "http://zouzou.com/mmupcawejx",
"domain": "chhbuqzrjx.gn",
"ip": "213.35.223.83",
"email": "m.spaotivv@phljcbty.sl"
}
]
}

结果

地址占位符

随机生成区域、省市县、邮政编码

占位符:

  • region 区域。如: 华南
  • county(true) 省市县。
  • zip 邮政编码。
const Mock = require('mockjs')  // 导入mock
const data = Mock.mock({
// 定义数据生成规则
'empList|3': [{
'area': '@region', // 区域
'address': '@county(true)', // 省市县
'zipCode': '@zip' // 邮政编码
}]

})
console.log(JSON.stringify(data, null, 2)) // 打印数据

Vue--MockJs_数据_03

Vue--MockJs_属性值_04

{
"empList": [
{
"area": "西南",
"address": "广东省 梅州市 兴宁市",
"zipCode": "678513"
},
{
"area": "华北",
"address": "台湾 台东县 海端乡",
"zipCode": "923908"
},
{
"area": "西南",
"address": "江西省 抚州市 广昌县",
"zipCode": "118532"
}
]
}

结果