使用Jasmine在JavaScript中存储WebSocket

cie*_*bor 6 javascript testing stub websocket jasmine

我试着测试一下是否onmessage是一个合适的功能.

这是一个测试:

  describe(".init(address, window)", function() {
    beforeEach(function() {
      address = 'ws://test.address';
      window = {};
      e = {
        data: {}
      }
      spyOn(window, 'WebSocket').and.returnValue(function() {return {onmessage: null}});
      spyOn(subject, 'handleMessage');
    });

    it("should create a WebSocket client which connects to the given address", function() {
      subject.init(address, window);
      expect(window.WebSocket).toHaveBeenCalledWith(address);
    });

    it("should have onmessage method overriden with a function which handles message", function() {
      ws = subject.init(address, window);
      alert(JSON.stringify(ws));
      ws.onmessage(e);
      expect(subject.handleMessage).toHaveBeenCalledWith(e.data);
    });
  });
Run Code Online (Sandbox Code Playgroud)

这是实施:

FL.init = function(address, window) {
  if ('WebSocket' in window) {
    var ws = new WebSocket(address);
    ws.onmessage = function(e) {
      this.handleMessage(e.data);
    };
    return ws;
  }
};
Run Code Online (Sandbox Code Playgroud)

第一次测试通过.在第二,wsundefined.这是为什么?我尝试在控制台中new function() {return {onmessage: null}}看起来应该没问题.

tom*_*lec 11

我不完全确定我是否知道你的代码应该如何表现,但是如果你需要监视WebSocket构造函数和存根.send方法来模拟一些传入的消息,那么这里是如何实现它的.

要监视WebSocket你,你需要打电话.and.callThrough而不是打电话returnValue.然而,它导致有抱怨缺少的new关键字(如中提到这里),所以你需要假构造函数:

var realWS = WebSocket;
var WebSocketSpy = spyOn(window, "WebSocket").and.callFake(function(url,protocols){
  return new realWS(url,protocols);
});
Run Code Online (Sandbox Code Playgroud)

要为传入的消息制作间谍,您可以这样做

var onmessageCallbackSpy = jasmine.createSpy('onmessageCallback');
Run Code Online (Sandbox Code Playgroud)

你也可以窥探.send方法,并提供一些模拟的响应:

var sendSpy = spyOn(WebSocket.prototype, "send").and.callFake(function(outMsg){
  // process/check outgoing message
  // setTimeout, or call it immediately
  this.onmessage("mock message goes here");
}); 
Run Code Online (Sandbox Code Playgroud)

WebSocket.prototype在更换之前一定要使用WebSocketSpy.

如此完整的工作示例,应该如下所示:

it("should spy and callFake WebSocket constructor, and stub prototype methods", function (done) {
    var realWS= WebSocket;  
    var sendSpy = spyOn(WebSocket.prototype, "send").and.callFake(function(outMsg){
      if(outMsg == "outgoing message"){
        this.onmessage("incoming mocked message goes here");
      }
    });  
    // var messageSpy = spyOn(WebSocket.prototype, "onmessage");//.and.returnValue("mock message goes here");      
    var WSSpy = spyOn(window, "WebSocket").and.callFake(function(url,protocols){
      return new realWS(url,protocols);
    }); 
    var onmessageCallbackSpy = jasmine.createSpy('onmessageCallback');       

    // Your code
    // (function init(url, onmessageCallbackSpy){
        var ws = new WebSocket("ws://some/where");
        ws.onmessage = onmessageCallbackSpy;
        // code that results with receiving a message
        // or mocked send, that calls `.onmessage` immediately
        ws.send("outgoing message");
    // })();    

    expect(WSSpy).toHaveBeenCalledWith("ws://some/where");
    expect(onmessageCallbackSpy).toHaveBeenCalledWith("mock message goes here");
    done();
});
Run Code Online (Sandbox Code Playgroud)