jer*_*son 126 javascript unit-testing mocking requirejs
我有一个我想测试的AMD模块,但我想模拟它的依赖项而不是加载实际的依赖项.我正在使用requirejs,我的模块的代码看起来像这样:
define(['hurp', 'durp'], function(Hurp, Durp) {
return {
foo: function () {
console.log(Hurp.beans)
},
bar: function () {
console.log(Durp.beans)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我怎么能模拟出来hurp
,durp
所以我可以有效地进行单元测试?
And*_*rle 64
所以在阅读这篇文章后,我想出了一个解决方案,它使用requirejs配置函数为你的测试创建一个新的上下文,你可以简单地模拟你的依赖:
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/'
});
}
Run Code Online (Sandbox Code Playgroud)
因此,它创建了一个新的上下文,其中定义Hurp
和Durp
将由您传递给函数的对象设置.这个名字的Math.random可能有点脏,但它有效.因为如果您需要进行大量测试,则需要为每个套件创建新的上下文以防止重复使用模拟,或者在需要真正的requirejs模块时加载模拟.
在你的情况下,它看起来像这样:
(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');
})
});
});
})();
Run Code Online (Sandbox Code Playgroud)
所以我在生产中使用这种方法已有一段时间了,它非常强大.
bus*_*ted 44
你可能想看看新的Squire.js lib
来自文档:
Squire.js是Require.js用户的依赖注入器,可以轻松实现模拟依赖项!
jer*_*son 17
我找到了解决这个问题的三种不同解决方案,其中没有一种令人愉快
define('hurp', [], function () {
return {
beans: 'Beans'
};
});
define('durp', [], function () {
return {
beans: 'durp beans'
};
});
require('hurpdhurp', function () {
// test hurpdurp in here
});
Run Code Online (Sandbox Code Playgroud)
的fugly.你必须使用大量的AMD样板来混乱你的测试.
这涉及使用单独的config.js文件来定义指向模拟而不是原始依赖项的每个依赖项的路径.这也很难看,需要创建大量的测试文件和配置文件.
这是我目前的解决方案,但仍然是一个可怕的解决方案.
您可以创建自己的define
函数,为模块提供自己的模拟,并将测试放入回调中.然后你eval
运行你的测试模块,如下所示:
var fs = require('fs')
, hurp = {
beans: 'BEANS'
}
, durp = {
beans: 'durp beans'
}
, hurpDurp = fs.readFileSync('path/to/hurpDurp', 'utf8');
;
function define(deps, cb) {
var TestableHurpDurp = cb(hurp, durp);
// now run tests below on TestableHurpDurp, which is using your
// passed-in mocks as dependencies.
}
// evaluate the AMD module, running your mocked define function and your tests.
eval(hurpDurp);
Run Code Online (Sandbox Code Playgroud)
这是我的首选解决方案.它看起来有点神奇,但它有一些好处.
eval
愤怒地使用,想象一下Crockford会愤怒地爆发.显然,它仍然有一些缺点.
define
在每个测试中进行模拟,因为这是您的测试实际运行的地方.我正在研究一个测试运行器,为这种东西提供更好的语法,但我仍然没有解决问题1的好方法.
在requirejs嘲笑deps很难.我发现了一种有效的方式,但我仍然不满意.如果您有任何更好的想法,请告诉我.
Art*_*rov 15
有一个config.map
选项http://requirejs.org/docs/api.html#config-map.
关于如何使用它:
expicitely配置RequireJS;
requirejs.config({
map: {
'source/js': {
'foo': 'normalModule'
},
'source/test': {
'foo': 'stubModule'
}
}
});
Run Code Online (Sandbox Code Playgroud)在这种情况下,对于普通代码和测试代码,您可以使用相应的foo
实模块引用和存根的模块.
您可以使用testr.js来模拟依赖项.您可以将testr设置为加载模拟依赖项而不是原始依赖项.以下是一个示例用法:
var fakeDep = function(){
this.getText = function(){
return 'Fake Dependancy';
};
};
var Module1 = testr('module1', {
'dependancies/dependancy1':fakeDep
});
Run Code Online (Sandbox Code Playgroud)
看看这个:http://cyberasylum.janithw.com/mocking-requirejs-dependencies-for-unit-testing/
归档时间: |
|
查看次数: |
31212 次 |
最近记录: |