使用 Jasmine 在 AngularJS 中测试去抖函数从不调用该函数
Posted
技术标签:
【中文标题】使用 Jasmine 在 AngularJS 中测试去抖函数从不调用该函数【英文标题】:Testing a debounced function in AngularJS with Jasmine never calls the function 【发布时间】:2016-04-02 19:03:53 【问题描述】:我在使用下划线去抖动的服务中有一个方法。
该方法内部是对不同服务上的方法的调用。我正在尝试测试是否调用了不同的服务。
在我尝试测试去抖动方法时,从未调用不同服务的方法,并且 jasmine 失败并显示:
“预期的间谍 aMethod 已被调用。”
我知道它被调用(它在 chrome 中记录到控制台),它只是在期望已经失败之后才被调用。
所以...(最好)不添加 Sinon 或其他依赖项并且使用 给予解决方案的奖励积分*不必将 _.debounce 变成 $timeout...
怎么做?
angular.module('derp', [])
.service('herp', function()
return
aMethod: function()
console.log('called!');
return 'blown';
;
)
.service('Whoa', ['herp', function(herp)
function Whoa()
var that = this;
this.mindStatus = 'meh';
this.getMind = _.debounce(function()
that.mindStatus = herp.aMethod();
, 300);
return Whoa;
]);
测试:
describe('Whoa', function()
var $injector, whoa, herp;
beforeEach(function()
module('derp');
inject(function(_$injector_)
var Whoa;
$injector = _$injector_;
Whoa = $injector.get('Whoa');
herp = $injector.get('herp');
whoa = new Whoa();
);
);
beforeEach(function()
spyOn(herp, 'aMethod').andCallThrough();
);
it('has a method getMind, that calls herp.aMethod', function()
whoa.getMind();
expect(herp.aMethod).toHaveBeenCalled();
);
);
为什么 AngularJS 测试之神抛弃了我?
* 我不知道如何在 *** 上给出实际的奖励积分,但如果可能的话,我会的。
【问题讨论】:
【参考方案1】:我的去抖函数接受了参数,所以我像这样嘲笑_.debounce
spyOn(_, 'debounce').and.callFake(function(cb) return cb);
(对@Wawy 的回答稍作修改)
【讨论】:
【参考方案2】:你只需要模拟 lodash debounce 方法:
describe('Whoa', function()
var $injector, whoa, herp;
beforeEach(function()
module('derp');
spyOn(_, 'debounce').and.callFake(function(cb) return function() cb(); );
inject(function(_$injector_)
var Whoa;
$injector = _$injector_;
Whoa = $injector.get('Whoa');
herp = $injector.get('herp');
whoa = new Whoa();
);
);
beforeEach(function()
spyOn(herp, 'aMethod').andCallThrough();
);
it('has a method getMind, that calls herp.aMethod', function()
whoa.getMind();
expect(herp.aMethod).toHaveBeenCalled();
);
);
【讨论】:
不。还是行不通。在我们的两种情况下,都调用了 herp.aMethod,但在期望之前都没有调用。 我希望我现在能像承诺的那样拥有柴。 “最终”会解决这个问题。 在callfake里面的匿名函数里面放一个断点,然后检查堆栈看看它是从哪里调用的。 模拟函数真的被调用了吗? @AndrewLuhring 我已经编辑了我的答案。我现在意识到为什么它不起作用,在注入器实例化您的服务之后间谍正在完成,所以为时已晚。现在,它应该可以工作了。【参考方案3】:Angular $timeout
在测试中具有优势,因为它在测试中被模拟为同步。当使用第三方异步工具时,不会有这个优势。一般来说,异步规范看起来像这样:
var maxDelay = 500;
...
it('has a method getMind, that calls herp.aMethod', function (done)
whoa.getMind();
setTimeout(function ()
expect(herp.aMethod).toHaveBeenCalled();
done();
, maxDelay);
);
由于 Underscore debounce
不提供 flush
功能(而最新版本的 Lodash debounce
does),异步测试是最好的选择。
【讨论】:
以上是关于使用 Jasmine 在 AngularJS 中测试去抖函数从不调用该函数的主要内容,如果未能解决你的问题,请参考以下文章
在 Jasmine 单元测试中模拟 AngularJS 模块依赖项
使用 Jasmine 在 AngularJS 中测试去抖函数从不调用该函数
Chutzpah - 使用 jasmine 和 TypeScript 进行 AngularJS 测试
使用 Jasmine 对包含私有超时的单元测试 Angularjs 指令