我有以下测试:
it('Should keep location when user rejects confirmation', inject(function ($controller, $rootScope) {
var confirmStub = sinon.stub(),
eventStub = {
preventDefault: sinon.spy()
};
miscServiceStub = function () {
this.confirm = confirmStub;
};
confirmStub.returns(false);
initializeController($controller, 'Builder', $rootScope);
$rs.$broadcast('$locationChangeStart', eventStub);
expect(confirmStub).toHaveBeenCalledOnce();
expect(confirmStub).toHaveBeenCalledWith('Are you sure you want to leave? you will loose any unsaved changes.');
expect(eventStub.stopPropagation).toHaveBeenCalledOnce();
miscServiceStub = function () {};
}));
测试此代码:
$rootScope.$on('$locationChangeStart', function (event) {
dump(arguments);
if (!$miscUtils.confirm('Are you sure you want to leave? you will loose any unsaved changes.')){
event.preventDefault();
}
});
event。$ stopPropagation不调用mock事件,dump(arguments)显示它正在真实事件对象之后传递给事件:
Chromium 31.0.1650 (Ubuntu) DUMP: Object{
0: Object{name: '$locationChangeStart', targetScope: Scope{$id: ..., $$childTail: ..., $$childHead: ..., $$prevSibling: ..., $$nextSibling: ..., $$watchers: ..., $parent: ..., $$phase: ..., $root: ..., this: ..., $$destroyed: ..., $$asyncQueue: ..., $$postDigestQueue: ..., $$listeners: ..., $$isolateBindings: ..., activeTab: ..., routeParams: ...}, preventDefault: function () { ... }, defaultPrevented: false, currentScope: Scope{$id: ..., $$childTail: ..., $$childHead: ..., $$prevSibling: ..., $$nextSibling: ..., $$watchers: ..., $parent: ..., $$phase: ..., $root: ..., this: ..., $$destroyed: ..., $$asyncQueue: ..., $$postDigestQueue: ..., $$listeners: ..., $$isolateBindings: ..., activeTab: ..., routeParams: ...}},
1: Object{stopPropagation: spy}
}
我怎样才能使它成为事件对象是模拟事件而不是真实事件对象本身?我是以正确的方式接近这个吗?我对Angular很陌生,对代码/测试的任何评论都会非常感激。
如果您需要更多相关代码,请告诉我。
答案 0 :(得分:36)
$scope.$broadcast
返回Event
对象,因此您可以执行此操作:
var event = $scope.$broadcast("someEvent");
expect(event.defaultPrevented).toBeTruthy();
答案 1 :(得分:3)
在这一行:
$rs.$broadcast('$locationChangeStart', eventStub);
您提供的参数将与事件一起传输,而不是事件本身。这就是你到达这里的原因:
$rootScope.$on('$locationChangeStart', function (event)
2个对象作为参数。您活动的完整签名应为:
$rootScope.$on('$locationChangeStart', function (event, eventStub)
所以:你不能以你尝试过的方式测试stopPropagation的调用。
如果您查看了角度src(第12185行......),您将看到创建的事件没有任何模拟此对象的可能性。 $ scope本身并没有被angular-mock嘲笑。
如果要测试的是调用了preventDefault,我会编写一个具有调用preventDefault函数的服务。这项服务可以轻松实现。