我一直在寻找解决方案很长一段时间没有运气,我有以下代码我想测试:
some_script.js
var Model = require('./models')
exports.tokenizeCard = function (args) {
var model = new Model('SOME_NAME', args);
return utils.postXMLRequest('SOME_URL'), model.xml);
}
models.js
class models {
constructor(model, args, order) {
this.xml = '<fake>some_text</fake>'
}
}
我想存根该构造函数,以便我可以返回一个自定义测试对象,或者失败,整个类。我知道我可以有一些函数返回一个新的实例nad stub函数,如下所示:
exports.tokenizeCard = function (args) {
var model = getModel(args);
...
}
function getModel(args){
return new Model(args))
}
但是如果可能的话,我真的想直接避免这种情况和存根,如果有人有解决方案,我将非常感激。
通常,我使用以下lib之一来执行此操作:
下面有3个不同的样本:
// using rewire
const rewire = require('rewire');
const lib = rewire('some_script.js')
describe('some script', () => {
it('tokenizeCard', () => {
const modelStub = sinon.stub();
const revert = lib.__set__('Model', modelStub);
lib.tokenizeCard('foo', 'bar');
modelStub.calledWithNew();
modelStub.calledWith('SOME_NAME', 'foo', 'bar');
revert();
});
});
// using babel-plugin-rewire
import lib, {__RewireAPI__} from 'some_script.js'
describe('some script', () => {
it('tokenizeCard', () => {
const modelStub = sinon.stub();
__RewireAPI__.__Rewire__('Model', modelStub);
lib.tokenizeCard('foo', 'bar');
modelStub.calledWithNew();
modelStub.calledWith('SOME_NAME', 'foo', 'bar');
__RewireAPI__.__ResetDependency__('Model');
});
});
// using mockery
//
// NOTE:
// This one will work only if you have dynamic require
// Let's say you have
// var Model = require('./models')
// inside tokenizeCard
const mockery = require('mockery');
const lib = require('some_script.js')
describe('some script', () => {
before(() => {
mockery.enable();
});
after(() => {
mockery.disable();
});
afterEach(() => {
mockery.deregisterAll();
});
it('tokenizeCard', () => {
const modelStub = sinon.stub();
mockery.registerMock('./models', modelStub);
lib.tokenizeCard('foo', 'bar');
modelStub.calledWithNew();
modelStub.calledWith('SOME_NAME', 'foo', 'bar');
});
});
第三个选项将消除对hacky导入补丁的需求将是have the caller inject it,因此tokenizeCard
不再直接依赖于Model
。
这将允许调用者提供一个模型,因此生产代码可以使用Model
,您的测试代码可以简单地创建存根并使用它调用tokenizeCard
。
var Model = require('./models')
exports.tokenizeCard = function (args, M) {
M = M || Model;
var model = new M('SOME_NAME', args);
return utils.postXMLRequest('SOME_URL'), model.xml);
}
以上是一个中间重构,有一半打破了依赖。不指定M
将默认为Model
,但在测试中提供M
作为存根允许您配置存根对象并验证tokenizeCard
的工作方式比存根/修补Model
更容易,更易于维护。