使用 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();
    });
  });

但测试失败,间谍从未被击中。来自控制台调试语句的额外信息:

我的测试在这里缺少什么?

它正在发生,因为在你的 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 重现。