Angular - 用 jasmine 测试 websocket 包装器

Posted

技术标签:

【中文标题】Angular - 用 jasmine 测试 websocket 包装器【英文标题】:Angular - Testing a websocket wrapper with jasmine 【发布时间】:2015-05-08 20:33:02 【问题描述】:

我在测试我的 websocket 包装器时遇到问题:data-service 是我的 Angular 服务,用于包装本机浏览器 WebSocket 实现。

实施:

angular.module('core').factory('dataService', function ($interval, webSocket) 

  var sock;

  function openSocket() 
    sock = new webSocket('ws://localhost:9988');
  

  function isReady() 
    return sock.readyState === 1;
  

  openSocket();

  $interval(function () 
    !isReady() && openSocket();
  , 5000);
);

webSocket 是 window.WebSocket 提取到一个角度常数。

测试:

describe('Data Service', function () 

  var dataService,
    ws;

  jasmine.DEFAULT_TIMEOUT_INTERVAL = 15000;

  beforeEach(function () 
    module('core', function ($provide) 
      ws = jasmine.createSpy('constructor');
      $provide.constant('webSocket', ws);
    );

    inject(function (_dataService_) 
      dataService = _dataService_;
    );
  );

  it('should attempt to connect on load', function () 
    expect(ws).toHaveBeenCalled();
  );

  it('should attempt to reconnect every 5 seconds', function (done) 
    setTimeout(function () 
      expect(ws.calls.count()).toBe(2);
      done();
    , 6000);
  );
);

应尝试在加载时连接

通过:按预期调用了一次。

应该每 5 秒尝试重新连接一次

失败:无论我传递给setTimeout 的超时时间如何,它都只会被调用一次。我想知道这是否是由于每次使用 new 关键字重新连接尝试都会重新实例化套接字。我不太熟悉在 javascript 中使用 new 与使用普通函数构造对象有何不同。

我错过了什么吗?还是浏览器的 WebSocket 只是测试起来很痛苦?

【问题讨论】:

【参考方案1】:

在测试中避免超时问题的一种方法是通过调用 $interval.flush 强制应用程序时间向前移动来使其完全同步

it('should attempt to reconnect every 5 seconds', function () 
  $interval.flush(4999);
  expect(ws.calls.count()).toBe(1);
  $interval.flush(1);
  expect(ws.calls.count()).toBe(2);
  $interval.flush(4999);
  expect(ws.calls.count()).toBe(2);
  $interval.flush(1);
  expect(ws.calls.count()).toBe(3);
);

然后,您可以在几毫秒的挂钟时间内模拟 10 秒的应用程序时间。您可以在http://plnkr.co/edit/lz2u08JQLGCgGvX3vKQx 看到这一点

我怀疑为什么原来的不起作用,是测试环境中的 mock implementation of $interval实际上并没有调用真正的Javascript setInterval/setTimeout:它只是提供了flush将其向前移动一段模拟时间的功能。

【讨论】:

效果很好!我没有意识到 $interval 的模拟实现会阻止它正常工作。

以上是关于Angular - 用 jasmine 测试 websocket 包装器的主要内容,如果未能解决你的问题,请参考以下文章

如何为combineLatest rxjs Angular编写Jasmine Unit测试用例

如何在 Angular 7 中使用 Karma/Jasmine 为 App_Initializer 编写单元测试用例

如何使用 angular9 和 Jasmine 为所有组件生成 .pdf 格式的单元测试用例代码覆盖率报告

通过 Webpack(终端)执行 Typescript Jasmine 测试以测试 Angular2

Angular - Jasmine/karma - 订阅 lambda 表达式未执行

模拟指令以测试组件 - Angular 8 与 jasmine 和 Karma