如何使用squire模拟内联requirejs依赖项进行单元测试?

时间:2014-10-09 01:51:26

标签: javascript unit-testing requirejs mocha squirejs

我正在使用带有内联需求的requirejs,例如:

define(['someDep'], function(someDep) {
  return {
    someFn: function() {
      require(['anotherDep'], function(anotherDep) {
        anotherDep.anotherFn();
      });
    }
  } 
});

在我的特定情况下,我不能在定义中包含anotherDep

使用mocha进行测试时,我有一个这样的测试用例:

define(['squire'], function(Squire) {
  var squire = new Squire();
  describe('testcase', function() {
    it('should mock anotherDep', function(done) {
      var spy = sinon.spy();
      squire.mock('anotherDep', {
        anotherFn: spy
      });
      squire.require(['someDep'], function(someDep) {
        someDep.someFn();
        expect(spy).to.have.been.calledOnce;
        done();
      });
    });
  });
});

失败,因为anotherDep直接调用了require而不是squire.require。解决方法是替换全局范围中的require

var originalRequire;

before(function() {
  originalRequire = require;
  require = _.bind(squire.require, squire);
});

after(function() {
  require = originalRequire;
});

这是有效的(请注意squire.require必须以某种方式绑定到squire对象,我使用下划线来执行此操作),但是由于时间原因,仍然不会调用间谍。测试还必须改为

it('should mock anotherDep', function(done) {
  squire.mock('anotherDep', {
    anotherFn: function() {
      done();
    }
  });
  squire.require(['someDep'], function(someDep) {
    someDep.someFn();
  });
});

有更好的方法吗?如果没有,希望这为遇到同样问题的其他人提供解决方案。

1 个答案:

答案 0 :(得分:4)

我没有试图专门做你想要做的事情,但在我看来,如果乡绅做得很彻底,那么要求require模块应该给你你想要的东西而不必弄乱全球requirerequire模块是一个特殊(和保留)模块,可以使本地require功能可用。例如,当您使用Common JS语法糖时,这是必要的。但是,只要您希望获得本地require,就可以使用它。再说一遍,如果乡绅做得很彻底,那么它给你的require应该是一个绅士控制的而不是某种原始的require

所以:

define(['require', 'someDep'], function (require, someDep) {
  return {
    someFn: function() {
      require(['anotherDep'], function(anotherDep) {
        anotherDep.anotherFn();
      });
    }
  } 
});