为项目添加mock的方法
1.安装依赖 "underscore": "^1.13.4", "util": "^0.12.3",
2.书写配置插件代码 mock-plugin.js
"use strict";
var sysFs = require("fs");
var jsVm = require("vm");
var sysUtil = require("util");
var sysPath = require("path");
var request = require("request");
var urlParser = require("url");
var queryString = require("querystring");
var _ = require("underscore");
var async = require("async");
var dataEncoding = "utf-8";
var mockManager = {
respFuncMap: {
proxy_pass: function (confResp, context, done) {
var mockUrlObj = urlParser.parse(confResp);
var mockQueryStringObj = queryString.parse(mockUrlObj.query);
var req = context.req;
var reqUrlObj = urlParser.parse(req.url);
var reqQueryStringObj = queryString.parse(reqUrlObj.query);
mockUrlObj.query = queryString.stringify(
{},
mockQueryStringObj,
reqQueryStringObj
);
mockUrlObj.search = "?" + mockUrlObj.query;
var proxyOptions = {
set_header: {},
};
proxyOptions.url = urlParser.format(reqUrlObj);
proxyOptions.headers = _.extend({}, req.headers, {
host: mockUrlObj.host,
});
var result;
var reqMethod = req.method.toUpperCase();
if (reqMethod === "GET") {
result = request.get(proxyOptions).pipe(context.resp);
} else if (reqMethod === "POST") {
result = request.post(proxyOptions).pipe(context.resp);
}
return result.on("end", function () {
return done();
});
},
raw: function (confResp, context, done) {
var jsonp = context.rule.jsonp || "callback";
var queryObj = context.req.query;
var callback;
for (var key in queryObj) {
if (key === jsonp) {
callback = queryObj[key];
}
}
var resp = context.resp;
var jsonString = mockManager.getContent(confResp);
if (callback) {
resp.setHeader("Content-Type", "application/x-javascript");
jsonString = [callback, "(", jsonString.trim(), ")"].join("");
} else {
resp.setHeader("Content-Type", "application/json");
}
resp.write(jsonString);
return done();
},
action: function (confResp, context, done) {
if (!sysUtil.isFunction(confResp)) {
var content = mockManager.getContent(confResp);
var mockRespBuffer = {
module: {},
};
var baseObj;
var resp = context.resp;
try {
jsVm.runInNewContext(content, mockRespBuffer);
baseObj = mockRespBuffer.module;
if (sysUtil.isFunction(baseObj.exports)) {
baseObj.exports(context.req, resp, context);
} else if (sysUtil.isObject(baseObj.exports)) {
resp.setHeader("Content-Type", "application/json");
resp.write(JSON.stringify(baseObj.exports), dataEncoding);
} else {
// TODO
}
} catch (e) {
console.log("执行", confResp, "失败:", e);
}
} else {
confResp(contex.req, resp, context);
}
return done();
},
},
init: function (mockConf) {
var confFileStat = sysFs.statSync(mockConf);
this.mockConf = mockConf;
this.mockConfMtime = confFileStat.mtime;
this.mockRules = [];
this.checkInterval = 1000;
this.doUpdate();
this.lastCheckTime = new Date();
},
getMockRule: function (url, method) {
var mockRules = this.mockRules;
var i, mockConfs, tmpRule, result;
for (var i = 0, mockConfs = mockRules.length; i < mockConfs; i++) {
tmpRule = mockRules[i];
if (sysUtil.isRegExp(tmpRule.pattern)) {
result = url.match(tmpRule.pattern);
} else {
if (method === "POST") {
result = url === tmpRule.pattern;
} else {
result = url.indexOf(tmpRule.pattern) === 0;
}
}
if (result) {
return tmpRule;
}
}
return null;
},
doResponse: function (mockRule, req, resp, options) {
var mockResp = mockRule.responder;
var actionKey = "action";
if (typeof mockResp === "string") {
actionKey = this.getActionKey(mockResp);
}
console.log(
"API REQUEST: ",
req.url,
" => mocked to => ",
sysPath.resolve(mockResp)
);
var respFunc = this.respFuncMap[actionKey];
var respTasks = [
function (seriesCallback) {
return respFunc(
mockResp,
{
req: req,
resp: resp,
rule: mockRule,
options: options,
},
seriesCallback
);
},
];
return async.series(respTasks, function (err) {
if (err) {
return resp.end(err);
} else {
return resp.end();
}
});
},
getActionKey: function (mockResp) {
var extName = sysPath.extname(mockResp);
if (/https?:\/\//.test(mockResp)) {
return "proxy_pass";
} else {
switch (extName) {
case ".json":
return "raw";
case ".js":
return "action";
default:
return "raw";
}
}
},
doUpdate: function () {
var self = this;
var nowMs = new Date();
if (nowMs - this.lastCheckTime >= self.checkInterval) {
var checkFileStat = sysFs.statSync(self.mockConf);
if (checkFileStat.mtime !== self.mockConfMtime) {
try {
var mockConfBuffer = {
module: {},
};
var content = sysFs.readFileSync(this.mockConf, dataEncoding);
jsVm.runInNewContext(content, mockConfBuffer);
var configObj = mockConfBuffer.module.exports;
var tmpRules = configObj.rules || [];
var tmpKey, tmpAction;
delete configObj.rules;
for (tmpKey in configObj) {
tmpAction = configObj[tmpKey];
tmpRules.push({
pattern: tmpKey,
responder: tmpAction,
});
}
self.mockRules = tmpRules;
} catch (e) {
console.log("mock配置文件出错:", e.toString());
}
}
}
},
getContent: function (relativePath) {
var dirname = sysPath.dirname(this.mockConf);
var filePath = sysPath.join(dirname, relativePath);
var targetPath;
if (sysFs.existsSync(filePath)) {
targetPath = filePath;
} else if (sysFs.existsSync(filePath + ".json")) {
targetPath = filePath + ".json";
} else if (sysFs.existsSync(filePath + ".js")) {
targetPath = filePath + ".js";
} else {
throw new Error("path:" + relativePath + " not exists");
}
return sysFs.readFileSync(targetPath, dataEncoding);
},
};
function noMock(req, resp, next) {
return next();
}
module.exports = function (options) {
var mockConf = options.mockConf;
if (mockConf) {
if (!sysFs.existsSync(mockConf)) {
console.log("mock 配置", mockConf, "不存在");
return noMock;
}
} else {
return noMock;
}
mockManager.init(mockConf);
return function (req, resp, next) {
mockManager.doUpdate();
var mockRule = mockManager.getMockRule(req.url, req.method.toUpperCase());
if (mockRule) {
return mockManager.doResponse(mockRule, req, resp, options);
} else {
return next();
}
};
};
3.建立mock配置文件 mock-conf.js
module.exports = {
/* 菜单数据mock 目标地址 : mock文件 for example:
"/moirai/user/getResource": "./test/getResource.js",
*/
};
4.在vue.config.js 或者 webpack的config文件中引入mock配置并使用
// 添加mock配置文件
before (app) {
// withMock 控制是否使用mock
if (withMock) {
let mockPlugin = require('./mock/mockPlugin')
app.use(mockPlugin({
mockConf: './mock/mockConfig.js'
}))
console.log('\n本地 mock 加载成功!\n')
}
}

浙公网安备 33010602011771号