考虑我的服务器文件中有以下代码:
// 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等。我这次宁愿写自己的模拟服务。任何想法/帮助?
答案 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);