【问题标题】:Angular - Testing a websocket wrapper with jasmineAngular - 用 jasmine 测试 websocket 包装器
【发布时间】: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 只是测试起来很痛苦?

【问题讨论】:

    标签: javascript angularjs unit-testing websocket jasmine


    【解决方案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 的模拟实现会阻止它正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-12
    • 1970-01-01
    • 2015-12-07
    • 2017-08-17
    • 2017-04-04
    • 1970-01-01
    相关资源
    最近更新 更多