我有一个作为函数导出的服务模块。我需要将一些东西传递给它,就像配置对象一样,所以它确实需要保留这个结构。我试图从服务中删除一个函数,但无法弄清楚。在我的应用程序中,我有一个函数可以在测试期间进行API调用,因此我想将其存根。 (我知道我必须以不同方式编写测试以处理异步问题)
// myService.js
module.exports = function(config) {
function foo() {
returns 'bar';
}
return {
foo: foo
};
};
// test.js
var config = require('../../config');
var request = require('supertest');
var chai = require('chai');
var expect = chai.expect;
var sinon = require('sinon');
var myService = require('./myService.js')(config);
describe('Simple test', function(done) {
it('should expect "something else", function(done) {
var stub = sinon.stub(myService, 'foo').returns('something else');
request(server) // this object is passed into my test. I'm using Express
.get('/testRoute')
.expect(200)
.expect(function(res) {
expect(res.body).to.equal('something else');
stub.restore();
})
.end(done);
});
});
* /testRoute I set up as a simple GET route that simply returns the value from myService.foo()
以上不起作用,我认为这与我的服务导出方式有关。如果我按如下所示编写服务,则存根工作正常。
module.exports = {
test: function() {
return 'something';
}
};
但同样,我需要能够将信息传递给模块,因此我希望将模块保留在上面的原始结构中。有没有办法从以这种方式导出的模块中存根函数?我也在寻找代理商,但不确定这是不是答案。
答案 0 :(得分:3)
测试存根不起作用的原因是每次调用模块初始值设定项时都会创建foo
函数。正如您所发现的,当您在模块上使用静态方法时,您就可以存根。
这个问题有多种解决方案 - 但最简单的方法是静态公开该方法。
// myService.js
module.exports = function(config) {
return {
foo: foo
};
};
var foo = module.exports.foo = function foo() {
return 'bar'
}
它很难看,但很有效。
如果foo函数对服务中的变量有一个闭包(这就是它存在于服务初始化程序中的原因),该怎么办?然后不幸的是,这些需要明确传入。
// myService.js
module.exports = function(config) {
return {
foo: foo
};
};
var foo = module.exports.foo = function(config) {
return function foo() {
return config.bar;
}
}
现在你可以安全地存根模块了。
但是,你如何存根应该被认为是不安全的。只有当您的测试完美无缺时,存根才会被清理干净。您应始终在before
和after
(或beforeEach
和afterEach
)灯具中存根,例如:
// We are not configuring the module, so the call with config is not needed
var myService = require('./myService.js');
describe('Simple test', function(done) {
beforeEach(function () {
// First example, above
this.myStub = sinon.stub(myService, foo).returns('something else');
// Second example, above
this.myStub = sinon.stub(myService, foo).returns(function () {
returns 'something else';
});
});
afterEach(function () {
this.myStub.restore();
});
it('should expect "something else", function(done) {
request(server) // this object is passed into my test. I'm using Express
.get('/testRoute')
.expect(200)
.expect(function(res) {
expect(res.body).to.equal('something else');
})
.end(done);
});
});
还有其他选项可以使用依赖项注入来存储依赖项。我建议您查看https://github.com/vkarpov15/wagner-core或我自己的https://github.com/CaptEmulation/service-builder