用sinon剔除条纹 – 使用stub.yields
我试图用sinon存根nodejs stripe api来testing客户的创build,使用如下的testing:
var sinon = require('sinon'); var stripe = require('stripe'); var controller = require('../my-controller'); var stub = sinon.stub(stripe.customers, 'create'); stub.create.yields([null, {id: 'xyz789'}]); //stub.create.yields(null, {id: 'xyz789'}); //same result with or without array controller.post(req, {}, done);
我的理解是, stub.create.yields
应该调用第一个callback,并传递它(在这种情况下)null,后面跟着一个ID为xyz789的对象。 这可能是我误解的地方
在我的'控制器'我有以下内容:
exports.post = function(req, res, next) { stripe.customers.create({ card: req.body.stripeToken, plan: 'standard1month', email: req.body.email }, function(err, customer) { console.log('ERR = ', err) console.log('CUSTOMER = ', customer)
错误和客户都是未定义的。
我做错了什么?
编辑
我认为这个问题可能在这里:(条纹文档)
var stripe = require('stripe')(' your stripe API key ');
所以, stripe
构造函数需要一个API键
在我的testing中,我不提供一个:var stripe = require('stripe');
但在我的控制器中,我有:
var stripe = require('stripe')('my-key-from-config');
所以,按照你的例子,我有:
test.js :
var controller = require('./controller'); var sinon = require('sinon'); var stripe = require('stripe')('test'); var stub = sinon.stub(stripe.customers, 'create'); stub.yields(null, {id: 'xyz789'}); //stub.create.yields(null, {id: 'xyz789'}); //same result with or without array controller.post({}, {}, function(){});
controller.js
var stripe = require('stripe')('my-key-from-config'); var controller = { post: function (req, res, done) { stripe.customers.create({ card: req.body, plan: 'standard1month', }, function(err, customer) { console.log('ERR = ', err); console.log('CUSTOMER = ', customer); }); } } module.exports = controller;
当你这样做:
var stripe = require('stripe')('my-key-from-config');
条纹库dynamic创buildcustomer
和其他对象。 所以,当你把它存储在一个文件中:
test.js
var stripe = require('stripe')('test'); var stub = sinon.stub(stripe.customers, 'create');
您的控制器创build另一个stripe
实例在另一个文件中使用:
controller.js
var stripe = require('stripe')('my-key-from-config'); var controller = { ... }
来自testing的残留版本对控制器的版本没有影响。
所以….
你可能需要将stripe
的testing实例注入到控制器中,或者使用像nock这样的库来模拟http级别的事情,如下所示:
nock('https://api.stripe.com:443') .post('/v1/customers', "email=user1%40example.com&card=tok_5I6lor706YkUbj") .reply 200, object: 'customer' id: 'cus_somestripeid'
看起来你正试图在Stripe API中从#stripe.customers.create()中分离出你的#post()函数。 @lambinator是正确的,指出客户对象是dynamic创build的,当你打电话
require('stripe')('my-key-from-config')
和
require('stripe')('test')
所以在testing中,你的stub不适用于控制器中的#stripe.customers.create()。
您可以将条带的testing实例注入到控制器中,如@lambinator所示。 注射是有史以来最好的事情。 但是,如果你正在编写一个橡胶 – 路上types的组件(如代理),注入是不合适的。 相反,您可以使用Stripe模块中提供的第二个导出:
Stripe.js:
…
// expose constructor as a named property to enable mocking with Sinon.JS module.exports.Stripe = Stripe;
testing:
var sinon = require('sinon'); var stripe = require('stripe')('test'); var StripeObjectStub = sinon.stub(Stripe, 'Stripe', function(){ return stripe; }); //NOTE! This is required AFTER we've stubbed the constructor. var controller = require('./controller'); var stub = sinon.stub(stripe.customers, 'create'); stub.create.yields([null, {id: 'xyz789'}]); //stub.create.yields(null, {id: 'xyz789'}); //same result with or without array controller.post({}, {}, function(){});
控制器:
require('stripe').Stripe('my-key-from-config'); var controller = { post: function (req, res, done) { stripe.customers.create({ card: req.body, plan: 'standard1month', }, function(err, customer) { console.log('ERR = ', err); console.log('CUSTOMER = ', customer); }); }
然后在你的控制器中#stripe.customers.create()将调用你的testing存根。
这可能不是你在这里描述的内容的一部分。
yield是callArg的一个别名 ,但试图调用第一个参数是一个函数,并使用Function.prototype.apply为它提供参数 – 这意味着@psquared是正确的,说它不需要是一个数组。
但是,这不是你的问题。 试图在JSFiddle中重新创build给定的代码,我们可以看到它成功callback了参数 。
var stripe = { customers: { create: function () {} } }; var controller = { post: function (req, res, done) { stripe.customers.create({ card: req.body, plan: 'standard1month', }, function(err, customer) { console.log('ERR = ', err); console.log('CUSTOMER = ', customer); }); } } var stub = sinon.stub(stripe.customers, 'create'); stub.yields(null, {id: 'xyz789'}); //stub.create.yields(null, {id: 'xyz789'}); //same result with or without array controller.post({}, {}, function(){});
这告诉我你需要展示更多的代码,或者尝试编写一个简化的testing用例来试图找出问题所在。