我有一个通过环境配置 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 被 stub 并显示当前时间。并且测试失败。它说 stub 从未被调用过。
我已经尝试了很多天了,但仍然没有成功。知道如何 stub knex 查询吗?
更新
在与它斗争了几个小时之后,我认为 stub 被跳过,因为应用程序在 stub 之前被实例化。所以 stub 永远不会被加载。
我的服务器结构就是这个结构。
--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);
});
};
我的模拟仍然被跳过,应用程序首先被调用。
最佳答案
您无法更改原始数据,因为 knexConnection
是函数而不是对象。
knexConnection().raw(...).then(...)
也就是说,它是一个返回一个对象的函数,该对象上有一个原始函数。
此外,我们还可以在处理 knexConnection 时 stub 它。因此我们可以控制 raw
是什么。
const promise = sinon.stub().resolves("Query executed")
const knexConnection = sinon.stub().returns({
raw: promise
})
还有一件事,我用过 Mocha。为了将 beforeEach 中的 stub 传递给它,我使用了 this.currentTest
(在 beforeEach
中)和 this.test
(在 it
中)。请参阅评论。
这使我的测试通过了:
// 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) })
})
}
如果您还有其他问题,请询问。
关于node.js - 如何模拟 route 使用的 knex 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57939272/