https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/basic_usage中获取示例代码,以下是由网络 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服务/工厂的一部分运行(在网络 worker 中运行的单独应用程序中?),因此我可以使用DI系统注入(inject)依赖项的模拟,并使单元测试代码看起来与其他服务的测试非常相似。我怎样才能做到这一点?

最佳答案

有一种方法可以执行此操作,其中在Web Worker中运行的主要代码作为单独的手动引导的Angular模块的一部分运行。

为了在Web Worker中加载Angular

  • 环境需要修补/猴子修补/被黑客入侵,因此Angular在加载和引导时不会由于缺少windowdocument对象
  • 而引发各种异常
  • 然后必须通过importScripts包括Angt_rli
  • 然后,必须通过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)。
    // 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);
        };
      });
    
    })();
    

    然后,可以使用与本来不是要在Web worker中运行的完全相同的测试来进行测试:
    // 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进行了测试。

    关于angularjs - Web Worker的单元测试代码,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27745813/

    10-09 19:57
    查看更多