我已经找了一段时间没有运气的解决方案,我有以下代码我想测试:
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))
}
但我真的希望尽可能避免这种情况和存根,如果有人有解决方案,我将非常感激。
答案 0 :(得分:0)
第3个选项可以删除对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
更加可维护。
答案 1 :(得分:0)
通常,我使用以下某个库来执行此操作:
以下有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();
});
});
&#13;
// 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');
});
});
&#13;
// 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');
});
});
&#13;