我已经使用pg-promise创建了一个基本的NodeJS微服务。我已经通过express:
创建了包含API的路由文件(index.js)var express = require('express');
var router = express.Router();
var db = require('./../queries');
router.get('/api/puppy', db.getAllPuppies);
router.post('/api/puppy', db.createPuppy);
module.exports = router;
然后我在queries.js文件中添加了两个函数:
var promise = require('bluebird');
var options = {
promiseLib: promise
};
var config = require('./config.json');
var pgp = require('pg-promise')(options);
var connectionString = process.env.DB_PATH || "postgres://postgres:xxxx@localhost:5432/postgres";
var db = pgp(connectionString);
function getAllPuppies(req, res, next) {
db.any('select * from puppy')
.then(function (data) {
res.status(200)
.json({
status: 'success',
data: data,
});
})
.catch(function (err) {
return next(err);
});
}
function createPuppy(req, res, next) {
db.none('insert into ' +
'puppy(name, description) ' +
'values(${name}, ${description})',
req.body)
.then(function () {
res.status(200)
.json({
status: 'success',
});
})
.catch(function (err) {
return next(err);
});
}
module.exports = {
getAllPuppies,
createPuppy,
};
该应用程序运行良好。我想以这种或那种方式测试这两个函数,但我对数据库应该被模拟的方式(我使用Mocha和诸如beforeEach之类的函数)来检索或创建数据。
答案 0 :(得分:2)
作为一般经验法则,您有两种选择:
要么是一个潜在有用的测试。第一个选项更多的是单元测试,并要求您重构代码以使用依赖注入。然后,您的测试代码将注入某种模拟对象,该对象具有与您的实际数据库对象相同的API。如果你对这类事情不熟悉,谷歌将成为你的朋友:单位测试和控制反转在概念上是相当直接的,但可能会有很多细节被卡住。
由于您还没有设置依赖注入,您可以做的下一件事是配置您的测试环境以使用某种测试数据库。这将使它更像是一个集成测试。您可以通过为测试设置不同的数据库来做到这一点,然后您(仍然)必须重构代码以根据您的环境调整数据库连接凭据。同样,它在概念上很简单,但可能会有很多细节迷失。
如果您不熟悉代码测试,那么花一些时间阅读它并真正了解其工作方式是值得的。阅读有关控制反转和单元测试的主题。正确的代码测试对任何代码库都是一个巨大的好处,但是你必须从一开始就计划它,因为适当的控制反转(这是正确的代码测试所必需的)确实需要以不同的方式组织你的代码。
编辑添加一些细节:
一旦您计划并执行代码测试,就可以非常轻松,但是开始使用并不是一项小任务。最重要的问题是您的代码必须以实际规划未来代码测试的方式编写。在您的情况下,这意味着要么重构代码以使用实际依赖项注入(node.js支持),要么至少根据环境调整数据库连接。后者会更容易做,但它只允许有限的测试。最后,如果你想进行正确的代码测试,你将不得不重构依赖注入/控制反转。
一旦你这样做,你的下一步将是选择一个测试框架。我不知道node.js的默认值是什么,但是大多数语言/框架都有一个相当标准的语言/框架,不应该很难找到。可能会有多个选项,因此您可能会花一些时间选择最适合您风格的选项。选择测试框架后,您将不得不阅读它的工作原理,如何设置以及如何使用它。
完成这些工作后,您实际上可以开始测试了。第一次这样做时需要做很多工作,但这是值得的。
答案 1 :(得分:1)
你正在做的一些事情会产生一些问题,从长远来看,这将是一个真正的问题。然而,让我们接近最大的罪犯:在你的路线文件中声明你的数据库。这是一个大禁忌,它应该只被声明一次并在需要时被要求。 pg-promise
here at the official demo的作者可以找到一个很好的例子。要注意的重点是分区化。如果您的设计不正确,那么测试就是您现在遇到的PITA。但是,如果你正确地划分它,那么当你编写测试时,你只需要传递模拟对象,并使用方法调用它,这将为你提供一个可测试的环境。
演示中最大的例子:
var options = {
// Use a custom promise library, instead of the default ES6 Promise:
promiseLib: promise,
// Extending the database protocol with our custom repositories:
extend: obj => {
// Do not use 'require()' here, because this event occurs for every task
// and transaction being executed, which should be as fast as possible.
obj.users = repos.users(obj, pgp);
obj.products = repos.products(obj, pgp);
// Alternatively, you can set all repositories in a loop:
//
// for (var r in repos) {
// obj[r] = repos[r](obj, pgp);
// }
}
};
有了这个你现在可以在Mocha中编写简单的模拟(我建议查看unitjs作为一些例子,但是当你将某些内容传递给测试时,你只需要传递一个{{1}带有req
对象且带有app
的{{1}}对象的对象....你明白了。
因此,最重要的是你设计错误(你的代码看起来很好)。您需要将事物重构为单独的部分,因此当您进行测试时,您实际上可以编写有意义的测试。