如何在 RequireJS 中模拟单元测试的依赖项?

我有一个AMD模块,我想测试,但我想模拟它的依赖关系,而不是加载实际的依赖关系。我正在使用 requirejs,我的模块的代码看起来像这样:

define(['hurp', 'durp'], function(Hurp, Durp) {
  return {
    foo: function () {
      console.log(Hurp.beans)
    },
    bar: function () {
      console.log(Durp.beans)
    }
  }
}

我怎样才能模拟出来,这样我就可以有效地进行单元测试?hurpdurp


答案 1

因此,在阅读这篇文章后,我想出了一个解决方案,该解决方案使用requirnjs配置函数为您的测试创建一个新的上下文,您可以在其中简单地模拟您的依赖项:

var cnt = 0;
function createContext(stubs) {
  cnt++;
  var map = {};

  var i18n = stubs.i18n;
  stubs.i18n = {
    load: sinon.spy(function(name, req, onLoad) {
      onLoad(i18n);
    })
  };

  _.each(stubs, function(value, key) {
    var stubName = 'stub' + key + cnt;

    map[key] = stubName;

    define(stubName, function() {
      return value;
    });
  });

  return require.config({
    context: "context_" + cnt,
    map: {
      "*": map
    },
    baseUrl: 'js/cfe/app/'
  });
}

因此,它创建了一个新的上下文,其中的定义将由您传递到函数中的对象设置。名称的Math.random可能有点脏,但它有效。因为如果你有一堆测试,你需要为每个套件创建新的上下文,以防止重用你的模拟,或者在你需要真正的 requirejs 模块时加载模拟。HurpDurp

在你的情况下,它看起来像这样:

(function () {

  var stubs =  {
    hurp: 'hurp',
    durp: 'durp'
  };
  var context = createContext(stubs);

  context(['yourModuleName'], function (yourModule) {

    //your normal jasmine test starts here

    describe("yourModuleName", function () {
      it('should log', function(){
         spyOn(console, 'log');
         yourModule.foo();

         expect(console.log).toHasBeenCalledWith('hurp');
      })
    });
  });
})();

因此,我在生产中使用这种方法一段时间,它非常健壮。


答案 2

您可能想查看新的 Squire.js lib

从文档:

Squire.js是 Require.js用户的依赖注入器,使模拟依赖关系变得容易!