如何用 sinon 存根对象方法?
How to stub an object method with sinon?
我需要存根 mh 对象的 sendMandrill 方法。
查看我正在测试的文件 (mail.js):
let MailHandler = require('../../modules/mail.handler.module');
...
let api = (router, parser) => {
let send = async (req, res, next) => {
let mh = new MailHandler();
mh.sendMandrill();
...
}
...
return router.post('/mail/send', parser.json(), send);
}
module.exports = api;
...
我的测试(mail.spec.js):
let stRequest = require('supertest');
let MailHandler = require('../../modules/mail.handler.module');
describe('my test', () => {
beforeEach(() => {
sinon.stub(MailHandler.prototype, 'sendMandrill', () => true);
})
it('stubs sendMandrill!', done => {
stRequest(app)
.post('/mail/send')
.end((err, resp) => {
done();
});
})
})
目前我收到以下错误:
TypeError: Cannot stub non-existent own property sendMandrill
添加 mail.handler.module - 请参阅下面的 mailHandler / sendMandrill 代码:
module.exports = mailHandler;
function mailHandler() {
...
var mandrill = require('../modules/mandrill');
var handler = {
sendMandrill: sendMandrill,
...
};
return handler;
function sendMandrill() {
mandrill.messages.sendTemplate({
message: {...}
});
}
...
}
您当前的方法为 mailHandler
工厂创建的每个实例创建一个新的 sendMandrill
。您实际上应该将其命名为 w/o new let mh = mailHandler()
或更好地将其重命名为 createMailHandler
以避免误用。
如果您想有效地使用原型继承,您需要重写 mailHandler
以实际使用 this
而不是新创建的对象。
var mandrill = require('../modules/mandrill');
module.exports = MailHandler;
function MailHandler() {
// use this instead of newly created object
this.foo = 'bar'
// avoid explicit return
// return handler;
}
// set methods to prototype
MailHandler.prototype.sendMandrill = function sendMandrill() {
// use this instead of handler here
mandrill.messages.sendTemplate({
message: {...}
});
}
使用上述方法,您将能够通过 sinon
存根原型属性,并证明使用 new
关键字调用构造函数。
UPD
如果您无法控制 mail.handler.module
,您可以使用允许模拟整个依赖项的 rewire
模块,或者将 MailHandler
作为 api
模块的一部分公开使其可注射。
api.MailHandler = require('../../modules/mail.handler.module')
let mh = api.MailHandler();
然后在测试中
let oldMailHandler;
beforeAll(() => { oldMailHandler = api.MailHandler})
afterAll(() => { api.MailHandler = oldMailHandler})
beforeEach(() => { api.MailHandler = function MockMailHandler() {} })
我需要存根 mh 对象的 sendMandrill 方法。
查看我正在测试的文件 (mail.js):
let MailHandler = require('../../modules/mail.handler.module');
...
let api = (router, parser) => {
let send = async (req, res, next) => {
let mh = new MailHandler();
mh.sendMandrill();
...
}
...
return router.post('/mail/send', parser.json(), send);
}
module.exports = api;
...
我的测试(mail.spec.js):
let stRequest = require('supertest');
let MailHandler = require('../../modules/mail.handler.module');
describe('my test', () => {
beforeEach(() => {
sinon.stub(MailHandler.prototype, 'sendMandrill', () => true);
})
it('stubs sendMandrill!', done => {
stRequest(app)
.post('/mail/send')
.end((err, resp) => {
done();
});
})
})
目前我收到以下错误:
TypeError: Cannot stub non-existent own property sendMandrill
添加 mail.handler.module - 请参阅下面的 mailHandler / sendMandrill 代码:
module.exports = mailHandler;
function mailHandler() {
...
var mandrill = require('../modules/mandrill');
var handler = {
sendMandrill: sendMandrill,
...
};
return handler;
function sendMandrill() {
mandrill.messages.sendTemplate({
message: {...}
});
}
...
}
您当前的方法为 mailHandler
工厂创建的每个实例创建一个新的 sendMandrill
。您实际上应该将其命名为 w/o new let mh = mailHandler()
或更好地将其重命名为 createMailHandler
以避免误用。
如果您想有效地使用原型继承,您需要重写 mailHandler
以实际使用 this
而不是新创建的对象。
var mandrill = require('../modules/mandrill');
module.exports = MailHandler;
function MailHandler() {
// use this instead of newly created object
this.foo = 'bar'
// avoid explicit return
// return handler;
}
// set methods to prototype
MailHandler.prototype.sendMandrill = function sendMandrill() {
// use this instead of handler here
mandrill.messages.sendTemplate({
message: {...}
});
}
使用上述方法,您将能够通过 sinon
存根原型属性,并证明使用 new
关键字调用构造函数。
UPD
如果您无法控制 mail.handler.module
,您可以使用允许模拟整个依赖项的 rewire
模块,或者将 MailHandler
作为 api
模块的一部分公开使其可注射。
api.MailHandler = require('../../modules/mail.handler.module')
let mh = api.MailHandler();
然后在测试中
let oldMailHandler;
beforeAll(() => { oldMailHandler = api.MailHandler})
afterAll(() => { api.MailHandler = oldMailHandler})
beforeEach(() => { api.MailHandler = function MockMailHandler() {} })