在NodeJS中运行单元测试时,如何更改服务需要模拟

时间:2017-03-07 15:33:59

标签: javascript node.js unit-testing

考虑我的服务器文件中有以下代码:

// Internal modules
const authenticationService = require('../services/authenticationService');
// Setup
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

// Init routing
require('./controllers/authenticationController')(app, authenticationService);

app.listen(8081, (err) => {
    if (err) throw new Error('Could not start the server');
});

现在这很好,并且会起作用。但是如果我运行单元测试并希望用模拟版本替换authenticationService呢?在针对我的API执行测试时,我不想访问我的真实数据库。我构建错误的方法或者我应该如何解决这个问题?我知道我可以使用不同的模拟模块来伪造authenticationService,但老实说我不喜欢太多使用sinon等。我这次宁愿写自己的模拟服务。任何想法/帮助?

2 个答案:

答案 0 :(得分:1)

Sinon是构建模拟/存根对象的好方法。

但它需要你将mock / stub对象注入到servrice代码中,前提是代码与依赖性反转原则一致

所以我认为rewire模块可以帮助你。通过使用重新连接,您可以轻松地重写覆盖依赖项,而无需修改现有代码。

答案 1 :(得分:1)

您需要的是dependency injection。而不是直接做

require('../services/authenticationService');

在您的模块中,您的模块应接受authenticationService作为依赖项。因此,如果将代码封装到模块中,请说SomeModule.js:

module.exports = function SomeModule(authenticationService, app, otherDependencies /* such as bodyParser etc. as needed. */) {
  this.start = function(port) {
    // your code goes here
    // more code
    app.listen(8081, (err) => {
       if (err) throw new Error('Could not start the server');
    });
  }
}

然后在您的生产代码中,您可以这样称呼它:

var myModule = new SomeModule(require('../services/authenticationService'), app /* and all other dependencies required by SomeModule.*/);
module.start(8081);

在您的测试代码中,您可以这样称呼它:

 var myModule = new SomeModule(require('../mocks/mockAuthenticationService'), app /* and all other dependencies required by SomeModule.*/);
 module.start(8081);