Web worker的单元测试代码(Unit test code of web worker)

编程入门 行业动态 更新时间:2024-10-28 04:15:21
Web worker的单元测试代码(Unit test code of 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系统来注入模拟依赖关系,并使单元测试代码看起来很像任何其他服务的测试。 我怎样才能做到这一点?

Taking the example code from https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/basic_usage , the following is run by a 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); }

run by code in an Angular service/factory

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

I would like to be able to unit test the code in worker.js, ideally running it as part of an Angular service/factory (in a separate app running in the web worker?), so I can use the DI system to inject mocks of dependencies, and have the unit test code looking much like the tests for any other service. How can I do this?

最满意答案

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

为了在Web worker中加载Angular

环境需要修补/猴子修补/黑客攻击,因此Angular在加载和引导由于缺少window和document对象时不会抛出各种异常 然后必须通过importScripts包含importScripts 然后必须通过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进行了测试。

There is a way to do this, where the main code run in a web worker is run as part of a separate, manually-bootstrapped, Angular module.

In order to load Angular in a web worker

The environment needs to be tinkered with/monkey patched/hacked so Angular doesn't throw various exceptions when it loads and bootstraps due to missing window and document objects Angular must then be included via importScripts Then the module you would like to run must be included via importScripts Then the module manually bootstrapped.

Example code that does this:

// 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']);

The code of the Angular module itself can then be very standard: with services/factories defined as desired. In this case, none are needed and I've opted to put the simple code of the example as a run callback (I've omitted the console.logs from the question).

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

This can then be tested using exactly the same tests as if it weren't meant to run in a 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); }); });

I'm not such a fan of hacking the environment to get Angular to load, as it feels very brittle to me, so other answers very welcome! The above code was tested using AngularJS v1.3.7.

更多推荐

本文发布于:2023-07-24 10:58:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1245061.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:单元测试   代码   worker   Web   web

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!