我对单元测试非常陌生(这是我使用QUnit的第一天,我以前从未使用过任何其他测试系统),我有点不清楚如何在一个QUnit页面中测试多个脚本文件中的内容,而不让脚本相互交互。我的意思是,比如说,如果我有script1.js
,它调用hello()
,而hello()
是在script2.js
中定义的,我如何在script1.js
上运行单元测试以确保它调用hello()
,但模拟hello()
的输出,使其成为真正的单元测试,然后运行script2.js
的hello()
。
基本上,我应该如何在一个QUnit页面中向另一个脚本隐藏一个脚本的全局变量和函数?
这完全取决于如何组织各种脚本文件以及整个系统。例如,如果您使用的是Angular,那么当您在另一个脚本文件中包含模块时,就可以注入依赖项。有一些工具可以嘲讽事物并"监视"函数调用,如Sinon,但这在很大程度上仍然取决于代码的组织方式。
为了便于讨论,假设这两个文件看起来是这样的,我们将忽略设计模式(尽管您应该认真考虑)。。。
// File A:
window.greeting = function() {
var world = hello();
return 'hello ' + world;
}
// File B:
window.hello = function() {
// possibly lots of code to determine what to return...
var value = 'foobar';
return value;
}
hello()
函数可以很容易地根据系统状态、用户输入等返回任何其他值。在我们的情况下,它没有,我们想做的是模拟文件B的代码,这样我们就不必测试它在做什么,只需要它返回一个字符串我们可以(也应该)用一个合适的mocking/依赖注入库来实现这一点然而,为了让您了解可以进行的最小设置,并了解一般方法,下面是我们的QUnit测试文件:
var _hello;
QUnit.module('File A', {
setup: function() {
_hello = window.hello; // hold onto the old value
// now we mock out hello()
window.hello = function() {
window.hello.called++; // track calls to it
return 'world'; // return our static value
}
window.hello.called = 0;
},
teardown: function() {
// put the old one back
window.hello = _hello || window.hello;
}
});
QUnit.test('Ensure greeting is correct', function(assert) {
var result = greeting();
assert.equal(window.hello.called, 1, 'hello should be called only once');
assert.equal(result, 'hello world', 'The greeting call should be "hello world"');
});
如果你想看到它运行,这里有一个jsfiddle。正如我所说,这是一个简单的例子,向您展示了如何做到这一点,但您应该研究适当的代码组织(想想AMD模块、require、Angular、Ember等)和适当的嘲讽库。