2014-04-18 25 views
5

Provo a verificare se onmessage è una funzione corretta.WebSocket di stub in JavaScript con Jasmine

Ecco un test:

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

Ecco l'attuazione:

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

Il primo test passa. Nel secondo, ws è undefined. Perché? Ho provato in una console new function() {return {onmessage: null}} e sembra che dovrebbe essere ok.

risposta

8

Non sono completamente sicuro di aver capito come dovrebbe comportarsi il tuo codice, ma se hai bisogno di spiare il metodo WebSocket costruttore e stub .send per deridere alcuni messaggi in arrivo, ecco come ottenerlo.

Per spiare il WebSocket è necessario chiamare .and.callThrough anziché returnValue. Tuttavia è risultato con lamenta per la mancanza di new parola chiave (come indicato nel here), quindi è necessario falsificare il costruttore:

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

Per effettuare una spia per i messaggi in arrivo si può semplicemente fare

var onmessageCallbackSpy = jasmine.createSpy('onmessageCallback'); 

Si può anche spiare .send metodo, e di fornire alcune risposte deriso con:

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"); 
}); 

Ma assicurati di usare WebSocket.prototype, prima di sostituirlo con WebSocketSpy.

Così pieno esempio di lavoro, dovrebbe essere simile a questo:

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

mi sono imbattuto in essa cercando di prendere in giro un websocket per i test di gelsomino. Ecco una soluzione che utilizza una finestra finta piuttosto estesa. WebSocket.

var socketMock; 
var windowMock; 
var address = 'ws://test.address'; 

describe(".init(address, window)", function() { 
    beforeEach(function() { 
    var WebSocket = jasmine.createSpy(); 
    WebSocket.and.callFake(function (url) { 
     socketMock = { 
     url: url, 
     readyState: WebSocket.CONNECTING, 
     send: jasmine.createSpy(), 
     close: jasmine.createSpy().and.callFake(function() { 
      socketMock.readyState = WebSocket.CLOSING; 
     }), 

     // methods to mock the internal behaviour of the real WebSocket 
     _open: function() { 
      socketMock.readyState = WebSocket.OPEN; 
      socketMock.onopen && socketMock.onopen(); 
     }, 
     _message: function (msg) { 
      socketMock.onmessage && socketMock.onmessage({data: msg}); 
     }, 
     _error: function() { 
      socketMock.readyState = WebSocket.CLOSED; 
      socketMock.onerror && socketMock.onerror(); 
     }, 
     _close: function() { 
      socketMock.readyState = WebSocket.CLOSED; 
      socketMock.onclose && socketMock.onclose(); 
     } 
     }; 
     return socketMock; 
    }); 
    WebSocket.CONNECTING = 0; 
    WebSocket.OPEN = 1; 
    WebSocket.CLOSING = 2; 
    WebSocket.CLOSED = 3; 

    windowMock = { 
     WebSocket: WebSocket 
    }; 
    spyOn(subject, 'handleMessage'); 
    }); 

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

    it("should have onmessage method overriden with a function which handles message", function() { 
    var message = 'hello socket'; 
    subject.init(address, window); 

    // pretend the socket connected (optional) 
    socketMock._open(); 

    // pretend the socket got a message 
    socketMock._message(message) 

    expect(subject.handleMessage).toHaveBeenCalledWith(message); 
    }); 
});