我正在尝试为一个新的Hapi应用程序设置一个测试模式。我过去在Express中使用过Mocha和Chai,但我正试图使用Lab和Code来留在Hapi生态系统中。我还使用Bookshelf和Knex来处理数据库交互。
所以我有一个简单的健康终点,我想测试一下。
'use strict';
const controller = require('../controller/healthController');
module.exports = [
{
method: 'GET',
path: '/health',
config: {
handler: controller.health,
description: 'The health endpoint returns 200',
tags: ['api', 'health']
}
}
];
在处理程序中,它只是执行一个快速查询,以确保它可以连接到数据库。
'use strict';
const bookshelf = require('../config/db');
const knex = bookshelf.knex;
module.exports = {
health: function (request, reply) {
knex.raw('SELECT version()').then(() => {
reply('service is running');
}).catch((err) => {
reply({err: err, code: 500});
});
}
};
据我所知,需要服务器然后使用server.inject实际上并不能启动服务器,所以我认为我不应该有数据库连接,这意味着我必须模拟数据库调用。奇怪的是,这个测试通过了:
'use strict';
const Code = require('code');
const Lab = require('lab');
const lab = exports.lab = Lab.script();
const describe = lab.describe;
const it = lab.test;
const expect = Code.expect;
const before = lab.before;
let server;
describe('health controller', () => {
before((done) => {
server = require('../../server');
done();
});
it('health check replies 200 when successful call to db', (done) => {
const options = {
method: 'GET',
url: '/health'
};
server.inject(options, (res) => {
expect(res.payload).to.include('is running');
expect(res.statusCode).to.equal(200);
done();
});
});
});
所以我有两个问题。首先,我觉得上面的测试不应该真的通过。除非它加载了所有内容,从而连接到数据库。也许我应该只测试控制器/处理程序方法?但我还没有找到任何这样的例子。
其次,无论如何,我都试图截取knex.raw调用,当我尝试像下面这样做时,我会得到500个错误。
'use strict';
const Code = require('code');
const Lab = require('lab');
const Sinon = require('sinon');
const lab = exports.lab = Lab.script();
const describe = lab.describe;
const it = lab.test;
const expect = Code.expect;
const before = lab.before;
let server;
let knex = require('../../app/config/db').knex;
describe('health controller', () => {
before((done) => {
server = require('../../server');
done();
});
it('health check replies 200 when successful call to db', (done) => {
const stub = Sinon.stub(knex, 'raw').returns({});
const options = {
method: 'GET',
url: '/health'
};
server.inject(options, (res) => {
expect(res.payload).to.include('is running');
expect(res.statusCode).to.equal(200);
expect(stub.calledOnce).to.be.true();
done();
});
});
});
我真的不知道为什么会发生这种事。
我认为Sinon.stub(knex, 'raw').resolves({});
是更好的解决方案
server.inject
的工作方式与您向真实服务器发出请求的方式完全相同。因此,如果测试运行时数据库已启动,端点将从数据库返回数据,就像手动启动服务器时一样。
Sinon.stub(knex, 'raw').returns({});
不起作用。knex.raw(…)
应返回Promise,而不是空对象。请尝试以下操作:
Sinon.stub(knex, 'raw').returns(Promise.resolve({}));
附带说明:记住在每次测试后调用server.stop()
,以确保测试之间没有持久的状态。一般来说,我认为您可以查看哈皮大学存储库中的示例测试文件。