Node - Stub类构造函数

问题描述 投票:0回答:2

我一直在寻找解决方案很长一段时间没有运气,我有以下代码我想测试:

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

但是如果可能的话,我真的想直接避免这种情况和存根,如果有人有解决方案,我将非常感激。

javascript node.js unit-testing sinon
2个回答
0
投票

通常,我使用以下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');
  });
});

0
投票

第三个选项将消除对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更容易,更易于维护。

© www.soinside.com 2019 - 2024. All rights reserved.