Node - Stub类构造函数

时间:2017-12-21 22:34:35

标签: javascript node.js unit-testing sinon

我已经找了一段时间没有运气的解决方案,我有以下代码我想测试:

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))
}

但我真的希望尽可能避免这种情况和存根,如果有人有解决方案,我将非常感激。

2 个答案:

答案 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种不同的样本:

&#13;
&#13;
// 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;
&#13;
&#13;

&#13;
&#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;
&#13;
&#13;

&#13;
&#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;
&#13;
&#13;

相关问题