如何使用sinon来模拟作为函数导出的节点模块的函数/属性?
我有一个作为function导出的服务模块。 我需要传递一些东西,像一个configuration对象,所以它需要保留这个结构。 我正在尝试从服务中删除一个函数,但无法弄清楚。 在我的应用程序,我有一个函数,使testing期间有问题的API调用,所以我想存根。 (我知道我必须写我的testing不同来处理asynchronous问题)
// 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'; } };
但是,我又需要能够将信息传递给模块,所以我想将模块保留在上面的原始结构中。 有没有一种方法来存储以这种方式导出的模块中的函数? 我也正在寻找代理,但不知道这是否是答案。
testing存根不起作用的原因是foo
函数每次调用模块初始化函数时都会创build。 正如你发现的那样,当你在模块上有一个静态方法时,你就可以存根。
这个问题有多种解决scheme,但最简单的方法是静态地公开方法。
// myService.js module.exports = function(config) { return { foo: foo }; }; var foo = module.exports.foo = function foo() { return 'bar' }
这是丑陋的,但工程。
如果foo函数对服务中的variables有一个闭包(这就是它存在于服务初始化程序中的原因)。 那么不幸的是,这些需要明确的传入。
// myService.js module.exports = function(config) { return { foo: foo }; }; var foo = module.exports.foo = function(config) { return function foo() { return config.bar; } }
现在,您可以安全地存根模块。
但是,如何剔除应该被认为是不安全的。 只有当你的testing完美的工作,存根被清理。 您应该始终在before
(或before
和after
)夹具存根,如:
// 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); }); });
还有其他选项可以使用dependency injection来存根相关性。 我build议你看看https://github.com/vkarpov15/wagner-core或我自己的https://github.com/CaptEmulation/service-builder