使用Jasmine异步测试postMessage并不起作用

时间:2015-06-11 18:12:21

标签: 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() {
    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被调用。
  • beforeEachit块都被调用。
  • 测试期间未调用控制器中的上述消息处理程序。
  • 此测试中发送的消息最终会被消息处理程序多次收到,但直到测试结束后才会收到。

我的测试缺少什么?

1 个答案:

答案 0 :(得分:6)

这种情况正在发生,因为在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重现。