Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/404.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用Jasmine async测试postMessage不';行不通_Javascript_Angularjs_Unit Testing_Jasmine_Postmessage - Fatal编程技术网

Javascript 使用Jasmine async测试postMessage不';行不通

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

我正在尝试使用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();
    });
  });
但是测试失败了,间谍从未被击中。放入控制台调试语句的额外信息:

  • 窗口。正在调用控制器中的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
回调中即可。不确定是否正确。