您的当前位置:首页正文

RESTful API接口的简单快速mock - nodejs实

来源:花图问答

什么是mock

mock一般常见于单元测试中。但也会在其他场景中见到,比如调用外部第三方服务时为了减少依赖,实现一个假的接口,这个接口返回的值和第三方接口返回的值是相同的,在开发环境、测试环境就调用这个假的接口,在生产环境则直接调用外部接口;这个假的接口有的公司叫挡板,有的公司叫MOCK。 微信支付mock

现在很多公司使用微服务架构,比如前端和后端同时开发,但后端的接口还没有开发好,那么前端可以调用一个假的MOCK的接口完成调试消除依赖,等后端接口开发好后再完成真正的接口。
对于自动化测试人员来说,只要知道了接口定义,就可以通过接口的MOCK来调试接口的自动化测试代码。

mock框架

准备工作

  • 安装最新版的node
  • 安装express npm install express
  • 安装supervisor npm install supervisor
  • 安装sync-request npm install sync-request
  • 安装body-parser npm install body-parser

注意:express, supervisor, body-parser这些依赖包最好在源代码文件所在目录安装,减少一些不必要的麻烦。或者使用npm -g安装

nodejs实现的简单mock

上面提到的那些开源框架功能很强大,但也显得笨重,我们也可以根据需要快速的实现一个简单的mock server,只要修改返回的json字符串用res.send()返回就可以很方便快捷的满足我们的需求。

源代码如下

//simple_mock.js
var express = require('express')
var app = express()
var bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json()); 
  
var map = {"1":{id:1,name:"bob"},"2":{id:2,name:"jack"}} 
  
app.get('/users',function(req, res){ 
    res.set({'Content-Type':'text/json','Encodeing':'utf8'});  
    res.send(map)  
})  

//Get方法,查找一个单一资源,在path里查询
app.get('/users/:id',function(req, res){  
    res.set({'Content-Type':'text/json','Encodeing':'utf8'});  
    res.send(map[req.param('id')])  
})  

//Post方法,创建一个单一资源 
app.post('/users/',  function(req, res){  
    res.set({'Content-Type':'text/json','Encodeing':'utf8'});  
    map[req.body.id] = req.body  
    res.send({status:"success",url:"/users/"+req.body.id}) 
})  

//Put方法,更新一个单一资源  
app.put('/users/:id', function(req, res){
    res.set({'Content-Type':'text/json','Encodeing':'utf8'});  
    map[req.body.id] = req.body  
    res.send({status:"success",url:"/users/"+req.param('id'),device:req.body});  
})  

//Delete方法,删除一个单一资源 
app.delete('/users/:id',function(req, res){ 
    res.set({'Content-Type':'text/json','Encodeing':'utf8'});  
    delete map[req.param('id')]  
    res.send({status:"success",url:"/users/"+req.param('id')})  
    console.log(map)  
})  

 //监听8888端口
app.listen(8888);

为了随时修改返回的数据并让修改自动生效,可以使用nodejs的supervisor模块运行mock脚本:
$ supervisor simple_mock.js

增强版的mock

有时候我们需要同时支持MOCK和真实的请求,简单的解决办法举个例子就是如果有个name参数的值传递是“张三”就转发到真实的请求并返回真实的返回值,如果不是“张三”就返回MOCK的信息。

对上面的代码稍作变化,对于GET方法,如果id是3就转发到真实的请求并返回真实的返回值,如果id不是3就返回假的mock的返回值:

//Get方法,查找一个单一资源,在query(header)里查询
app.get('/users/:id',function(req, res){  
    res.set({'Content-Type':'text/json','Encodeing':'utf8'});  
    console.log(req.param('id'))
    //如果请求的ID是3,就把请求转发到真实的API,假定真实的API地址是百度;如果ID不是3,返回MOCK的信息
    if(req.param('id') == '3'){
        var request = require('sync-request');
        var res2 = request('GET', 
        res.send(res2.getBody().toString()) 
    }else{
            res.send(map[req.param('id')])  
    }
})  

如果需要返回400,500这种网络错误,直接res.send('400')即可。

综上

上述快速实现的mock可以满足如下功能需求

  • 接口的mock(GET、POST、PUT、DELETE常见请求类型)
  • 同时支持mock和真实接口数据(json和其他类型)的返回
  • 可以返回400或者500等各种网络错误
  • 配置或者代码变更的实时生效