【问题标题】:Handling WebSocket connections in Jasmine tests在 Jasmine 测试中处理 WebSocket 连接
【发布时间】:2015-10-21 15:28:09
【问题描述】:

我有我的test.login.js

it('calls login when there\'s a username present', () => {
    React.findDOMNode(LoginElement.refs.username).value = 'foo';
    TestUtils.Simulate.submit(form);
    expect(LoginElement.state.errored).toEqual(false);
});

通过提交表单,它调用了一个登录方法:

login() {
    let typedUsername = React.findDOMNode(this.refs.username).value;
    if (!typedUsername) {
        return this.setState({
            errored: true
        });
    }
    // we don't actually send the request from here, but set the username on the AuthModel and call the `login` method below
    AuthModel.set('username', typedUsername);
    AuthModel.login();
},

所以我正在尝试测试Login.jsx 的功能,而不是AuthModel.js,但是通过调用AuthModel.login(),它会通过WebSocket 发送一条消息。但是,问题是在我的实际应用程序中,在 WebSocket 连接之前我不会加载任何东西(我触发一个事件然后呈现 React 应用程序),但是在我的 Jasmine 测试中,我不等待这个事件,所以我收到:

ERROR: null, DOMException{stack: 'Error: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.

我的测试失败了,它不应该失败,因为它封装的功能可以满足我的要求。它只是在依赖关系树上进一步出错。

解决此问题或减轻 WebSocket 尝试在我的测试环境中连接的最佳方法是什么? (我对测试非常陌生,所以这些概念现在对我来说非常陌生)

【问题讨论】:

    标签: javascript unit-testing websocket jasmine reactjs


    【解决方案1】:

    我不会假装对此了解很多,但是你不能依赖注入 AuthModel 那么如何在你的测试中模拟它?抱歉,这不是一个完整的答案,这只是我的第一直觉。

    如果您需要一个库来帮助解决这个问题,angular/di(来自 angular2)非常棒。

    【讨论】:

      【解决方案2】:

      您可以使用 Sinon JS 模拟/存根服务器请求。 - http://sinonjs.org/

      如果您只想知道 Auth.login 向服务器发出请求,请使用 sinon.stub (http://sinonjs.org/docs/#stubs),例如

      var stub = sinon.stub($, 'ajax');
      //Do something that calls $.ajax
      //Check stub was called and arguments of first call: 
      console.log(stub.called)
      console.log(stub.args[0])
      stub.restore();
      

      如果您的代码需要响应,请使用 sinon 的假服务器 (http://sinonjs.org/docs/#server):

      var server = sinon.fakeServer.create(),
          myResults = [1, 2, 3];
      
      //Set-up server response with correct selected tags
      server.respondWith('POST', url, [200, {
              'Content-Type': 'application/json'
          },
          JSON.stringify({
              response: myResults
          })
      ]);
      
      //Do something which posts to the server...
      sendToServer('abc').done(function(results) {
          console.log('checking for results ', results);
      })
      
      server.restore();
      

      服务器响应可能会变得更加复杂 - 使用函数等来处理多种请求类型,例如

      function initServer(respondOk) {
          var server = sinon.fakeServer.create();
      
          server.respondWith('POST', /.*\/endpoint\/.*/, function(request) {
              var header = { 'Content-Type': 'application/json' };
              if(!respondOk) {
                  var response = JSON.stringify([{
                      'error_code': '500',
                      'message': 'Internal server error'
                  }]);
                  request.respond(500, header, response);
              } else {
      
                  var code = 200,
                      resources = JSON.parse(request.requestBody),
                      result = JSON.stringify({ customer: resources });
      
                  request.respond(code, header, result);
              }
          });
      
          return server;
      });
      

      【讨论】:

      • 这太好了,谢谢!我想我仍然缺少一步,因为我的 Login.jsx 实际上 没有发出 AJAX(在我的情况下是 WebSocket)请求,而是导入 AuthModel,并调用 AuthModel.login (), 依次发出请求
      • 所以,本质上,我是在尝试确定是否调用了 AuthModel.login()...并不是说它随后发出了 WebSocket 请求,这并不重要(对于测试 Login.jsx)跨度>
      • 进一步处理您的请求 - 您可以存根 Auth.login - 它会在早期阶段拦截您的调用 - 因为如果您的 WebSocket 基础设施抛出错误,它可能不容易存根/模拟。
      • 如果 AuthModel.login 是原型方法,你可能需要这样做:sinon.stub(AuthModel.prototype, 'login')
      • 这就是我的想法。但是,如果我的想法是正确的——我无法从我的测试文件中获取 AuthModel,不是吗?在 Login.jsx 中,我只是从 './path/to/auth.js' 导入 AuthModel,我不导出它......所以它不会在 Login.jsx 实例上可用......
      猜你喜欢
      • 1970-01-01
      • 2017-04-14
      • 2020-12-27
      • 1970-01-01
      • 2013-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-16
      相关资源
      最近更新 更多