如何模拟路线中使用的 knex 函数
Posted
技术标签:
【中文标题】如何模拟路线中使用的 knex 函数【英文标题】:How to mock a knex function used in a route 【发布时间】:2020-01-16 06:04:55 【问题描述】:我有这个按环境配置knex的功能
const knexConnection = () =>
const config = require('./connection')[environment];
return knex(config)
我在我的 route.js 中使用了这个函数
module.exports = (app) =>
app.get("/test", (req,res)=>
knexConnection().raw("SELECT NOW() as time").then(result =>
const time = _.get(result.rows[0],'time')
res.send(time);
).catch(err => throw(err))
)
我的 route.js 测试文件
const sinon = require("sinon");
const chai = require("chai");
const mock = require('proxyquire')
const httpStatus = require('http-status');
const expect = chai.expect;
const myStub = sandbox.stub().resolves("Query executed")
const route = mock('../routes', '../../knexConntection':knexConnection : raw: myStub )
route(app)
chai.request(app)
.get('/test')
.set('content-type', 'application/x-www-form-urlencoded')
.end((err, res) =>
if (err) done(err);
expect(myStub).to.have.been.called;
expect(res.status).to.equal(200)
done();
)
当我执行测试文件时,knexConnection.raw 被存根并显示当前时间。并且测试失败。它说存根从未被调用过。
我已经尝试了几天,但仍然没有工作。知道如何存根 knex 查询吗?
更新
在挣扎了几个小时后,我发现存根被跳过了,因为应用程序在存根之前被实例化。所以存根永远不会被加载。
我的服务器结构有这个结构。
-- server.js
//...all server stuff
//load all modeles routes using route
route(app)
这是我的 index.js,因为我在服务器应用程序中动态加载所有路由。
var fs = require("fs");
module.exports = app =>
fs.readdirSync(__dirname).forEach(file =>
if (file == "index.js") return;
const name = file.substr(0, file.indexOf("."));
require("./" + name)(app);
);
;
我的模拟仍然被跳过,应用程序首先被调用。
【问题讨论】:
【参考方案1】:你不能改变 raw 因为knexConnection
是一个函数而不是一个对象。
knexConnection().raw(...).then(...)
也就是说,它是一个返回具有原始函数的对象的函数。
此外,我们还可以在处理 knexConnection 时将其存根。所以我们可以控制raw
是什么。
const promise = sinon.stub().resolves("Query executed")
const knexConnection = sinon.stub().returns(
raw: promise
)
还有一件事,我用过摩卡。为了将存根从 beforeEach 传递给它,我使用this.currentTest
(在beforeEach
)和this.test
(在it
)。见 cmets。
这使我的测试通过了:
// Import the dependencies for testing
const chai = require('chai');
const chaiHttp = require('chai-http');
const app = require('../server');
const route = require('../route');
const sinon = require("sinon");
const mock = require('proxyquire')
const httpStatus = require('http-status');
const expect = chai.expect;
chai.use(chaiHttp);
chai.should();
describe("test routes", () =>
beforeEach(function()
const promise = sinon.stub().resolves("Query executed")
// runs before all tests in this block
const knexConnection = sinon.stub().returns(
raw: promise
)
this.currentTest.myStub = promise //so as to access this in 'it' with this.test.myStub
// warning : './knex': knexConnection : knexConnection would replace knexConnection in route file
// with an object knexConnection : knexConnection causing the test to fail.
// Instead, you should write './knex': knexConnection
const route = mock('../route', './knex': knexConnection)
route(app)
);
it("should call myStub", function(done)
var myStub = this.test.myStub;
chai.request(app)
.get('/test')
.set('content-type', 'application/x-www-form-urlencoded')
.end((err, res) =>
if (err) done(err);
sinon.assert.called(myStub);
done();
)
)
it("should have 'Query executed' as text", function(done)
var myStub = this.test.myStub;
chai.request(app)
.get('/test')
.set('content-type', 'application/x-www-form-urlencoded')
.end((err, res) =>
if (err) done(err);
sinon.assert.match(res.text, "Query executed")
done();
)
)
it("should have 200 as status", (done) =>
chai.request(app)
.get('/test')
.set('content-type', 'application/x-www-form-urlencoded')
.end((err, res) =>
if (err) done(err);
expect(res.status).to.equal(200)
done();
)
)
)
路由文件:
const knexConnection = require('./knex.js');
module.exports = (app) =>
app.get("/test", (req,res)=>
knexConnection().raw("SELECT NOW() as time").then(result =>
res.send(result);
).catch(err => throw(err) )
)
如果您还有其他问题,请尽管提问。
【讨论】:
存根仍在被跳过。它说它被调用了 0 次。 @Ndx 有了这个精确的配置,我的测试就通过了。问题可能出在其他地方。尝试将 expect(res.status).to.equal(200) 更改为 expect(res).to.equal() 以进行调试。错误将显示 res 中的内容,特别是您需要检查 text 属性中的内容。你会看到有什么错误。 我在配置测试中唯一没有使用的是导入,因为它本身不支持。但这不应该是一个问题。而且我仍然将 res.body 作为当前时间戳,所以我的存根仍然无法正常工作。 @Ndx 确实如此。我修改了我的路由代码,如下所示: res.send(result) 并且我得到了'Query Executed' - >来自我的存根的文本。您的问题在于 proxyquire。 怎么样? proxyquire 可能有什么问题?附带说明一下,我已经重构了我的代码以将路由与控制器分开,但尚未成功覆盖所有测试***.com/questions/58209419/…以上是关于如何模拟路线中使用的 knex 函数的主要内容,如果未能解决你的问题,请参考以下文章