Javascript 使用Jasmine async测试postMessage不';行不通
我正在尝试使用Jasmine 2.0为AngularJS应用程序中的某些逻辑编写单元测试,但该逻辑在事件侦听器中。从控制器:Javascript 使用Jasmine async测试postMessage不';行不通,javascript,angularjs,unit-testing,jasmine,postmessage,Javascript,Angularjs,Unit Testing,Jasmine,Postmessage,我正在尝试使用Jasmine 2.0为AngularJS应用程序中的某些逻辑编写单元测试,但该逻辑在事件侦听器中。从控制器: window.addEventListener('message', function(e) { if (e.data === "sendMessage()") { $scope.submit(); } }, false); 从测试文件中: describe("post message", function() { bef
window.addEventListener('message', function(e) {
if (e.data === "sendMessage()") {
$scope.submit();
}
}, false);
从测试文件中:
describe("post message", function() {
beforeEach(function(done) {
var controller = createController(controllerParams);
spyOn($scope, 'submit');
window.postMessage('sendMessage()', '*');
done();
});
it('should submit on a sent message', function (done) {
expect($scope.submit).toHaveBeenCalled();
done();
});
});
但是测试失败了,间谍从未被击中。放入控制台调试语句的额外信息:
窗口。正在调用控制器中的addEventListener
- 调用每个之前的
和
块it
- 在测试期间,没有调用控制器中的上述消息处理程序
- 此测试中发送的消息最终会被消息处理程序接收数次,但直到测试结束后才会接收
我的测试在这里缺少什么?这是因为在每个块之前的
中调用window.postMessage()
(它是异步的,您不知道它何时执行),然后在它之后调用done()
,因为它是同步代码。但是window.postMessage()
是异步的,当异步操作完成时,基本上需要调用done()
。可以这样做:
beforeEach(function(done) {
spyOn(someObject, 'submit').and.callFake(function () {
done();
});
});
因此,当spy执行时,异步操作被视为完成
这可以表达得更短:
beforeEach(function(done) {
spyOn(someObject, 'submit').and.callFake(done);
});
以下是完整的代码:
var someObject = {
submit: function () {
console.log('Submit');
}
};
window.addEventListener('message', function(e) {
if (e.data === "sendMessage()") {
someObject.submit();
}
}, false);
// Test
describe('window.postMessage', function () {
beforeEach(function(done) {
spyOn(someObject, 'submit').and.callFake(function () {
done();
});
window.postMessage('sendMessage()', '*');
});
it('should submit on a sent message', function () {
expect(someObject.submit).toHaveBeenCalled();
});
});
查看一个正在工作的JS Bin:
我在这个示例中没有使用Angular,因为它可以用纯JS复制。您不应该在接收事件的窗口之外的另一个窗口上调用postMessage吗?(比如说,创建一个弹出窗口,就像在上所做的那样)尝试将其从窗口的弹出窗口更改为postmessage,而不是从窗口的postmessage,但所做的更改是,它没有太晚收到消息,而是根本没有收到消息。@AlanGordon:您已经找到解决方案了吗?我也有同样的问题;-)就是这样!谢谢你的帮助。有人知道为什么只有在间谍和邮件都在里面的情况下这才有效吗?如果我们将它包装在中(“…”,(完成)=>{}
将不起作用…我想我明白了。将expect(…).tohavebeencall()
放入和.fakeCall
回调中即可。不确定是否正确。