使用 Jasmine async 测试 postMessage 不起作用
Testing postMessage with Jasmine async doesn't work
我正在尝试使用 Jasmine 2.0 为 AngularJS 应用程序中的某些逻辑编写单元测试,但该逻辑位于事件侦听器中。来自控制器:
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();
});
});
但测试失败,间谍从未被击中。来自控制台调试语句的额外信息:
window.addEventListener
在控制器中被调用。
beforeEach
和 it
块都被调用了。
- 控制器中的上述消息处理程序在测试期间未被调用。
- 此测试中发送的消息最终会被消息处理程序多次接收,但直到测试结束后才会收到。
我的测试在这里缺少什么?
它正在发生,因为在你的 beforeEach
块中你调用 window.postMessage()
(这是异步的,你不知道它什么时候会执行)然后你立即调用 done()
它就像同步代码一样。但是 window.postMessage()
作为异步,基本上你需要在异步操作完成时调用 done()
。可以这样做:
beforeEach(function(done) {
spyOn(someObject, 'submit').and.callFake(function () {
done();
});
});
所以当你的间谍执行时,异步操作被认为是完成的。
这可以表达得更短:
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:http://jsbin.com/xikewogagu/1/edit?html,js,console,output
我没有在这个示例中使用 Angular,因为它可以用纯 JS 重现。
我正在尝试使用 Jasmine 2.0 为 AngularJS 应用程序中的某些逻辑编写单元测试,但该逻辑位于事件侦听器中。来自控制器:
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();
});
});
但测试失败,间谍从未被击中。来自控制台调试语句的额外信息:
window.addEventListener
在控制器中被调用。beforeEach
和it
块都被调用了。- 控制器中的上述消息处理程序在测试期间未被调用。
- 此测试中发送的消息最终会被消息处理程序多次接收,但直到测试结束后才会收到。
我的测试在这里缺少什么?
它正在发生,因为在你的 beforeEach
块中你调用 window.postMessage()
(这是异步的,你不知道它什么时候会执行)然后你立即调用 done()
它就像同步代码一样。但是 window.postMessage()
作为异步,基本上你需要在异步操作完成时调用 done()
。可以这样做:
beforeEach(function(done) {
spyOn(someObject, 'submit').and.callFake(function () {
done();
});
});
所以当你的间谍执行时,异步操作被认为是完成的。
这可以表达得更短:
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:http://jsbin.com/xikewogagu/1/edit?html,js,console,output
我没有在这个示例中使用 Angular,因为它可以用纯 JS 重现。