Web worker的单元测试代码

时间:2015-01-02 17:11:18

标签: angularjs unit-testing jasmine karma-runner web-worker

https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/basic_usage获取示例代码,以下内容由Web worker

运行
// in worker.js
onmessage = function(e) {
  console.log('Message received from main script');
  var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
  console.log('Posting message back to main script');
  postMessage(workerResult);
}

由Angular服务/工厂中的代码运行

var myWorker = new Worker("worker.js");

我希望能够在worker.js中对代码进行单元测试,理想情况下将其作为Angular服务/工厂的一部分运行(在web worker中运行的单独应用程序中?),这样我就可以使用DI系统注入依赖的模拟,并使单元测试代码看起来很像任何其他服务的测试。我怎么能这样做?

1 个答案:

答案 0 :(得分:2)

有一种方法可以做到这一点,其中在web worker中运行的主代码作为单独的,手动引导的Angular模块的一部分运行。

为了在Web worker中加载Angular

  • 环境需要修补/猴子修补/黑客攻击,因此Angular在加载和引导时会因为缺少windowdocument对象而引发各种异常
  • 然后必须通过importScripts
  • 包含Angular
  • 然后,您要运行的模块必须通过importScripts
  • 包含在内
  • 然后手动引导模块。

执行此操作的示例代码:

// worker.js

// Angular needs a global window object
var window = self;

// Skeleton properties to get Angular to load and bootstrap.
self.history = {};
var document = {
  readyState: 'complete',
  querySelector: function() {},
  createElement: function() {
    return {
      pathname: '',
      setAttribute: function() {}
    }
  }
};

// Load Angular: must be on same domain as this script
importScripts('angular.js');

// Put angular on global scope
angular = window.angular;

// Standard angular module definition
importScripts('worker-app.js');

// No root element seems to work fine
angular.bootstrap(null, ['worker-app']);

Angular模块本身的代码可以非常标准:根据需要定义服务/工厂。在这种情况下,不需要任何操作,并且我已选择将示例的简单代码作为run回调(我已从问题中省略了console.log)。< / p>

// worker-app.js
(function() {
  'use strict';

  var app = angular.module('worker-app', []);

  app.run(function($window) {
    $window.onmessage = function(e) {
      var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
      $window.postMessage(workerResult);
    };
  });

})();

然后可以使用完全相同的测试来测试它,就好像它不是要在网络工作者中运行一样:

// worker-app-spec.js
describe('worker-app', function() {
  'use strict';

  var $window;

  beforeEach(module('worker-app'));

  beforeEach(inject(function(_$window_) {
    $window = _$window_;
  }));

  beforeEach(function() {
    spyOn($window, 'postMessage');
  })

  it('attaches to $window onmessage', function() {
    var data = [2,3];
    var result = 'Result: ' + (data[0] * data[1]);
    $window.onmessage({data: data});
    expect($window.postMessage).toHaveBeenCalledWith(result);
  });
});

我不喜欢黑客环境让Angular加载,因为它对我来说感觉非常脆弱,所以其他答案非常受欢迎!上面的代码使用AngularJS v1.3.7进行了测试。