I try to test if onmessage
is a proper function.
Here is a 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);
});
});
Here is the implementation:
FL.init = function(address, window) {
if ('WebSocket' in window) {
var ws = new WebSocket(address);
ws.onmessage = function(e) {
this.handleMessage(e.data);
};
return ws;
}
};
The first test passes. In the second, ws
is undefined
. Why is that? I tried in a console new function() {return {onmessage: null}}
and it looks it should be ok.
I'm not completely sure that I figured out how your code is supposed to behave, but if you need to spy on WebSocket
constructor and stub .send
method to mock some incoming messages, here is how to achieve it.
To spy on WebSocket
you will need to call .and.callThrough
rather than returnValue
. However it result with complains about lack of new
keyword (as mentioned in here), so you need to fake the constructor:
var realWS = WebSocket;
var WebSocketSpy = spyOn(window, "WebSocket").and.callFake(function(url,protocols){
return new realWS(url,protocols);
});
To make a spy for incoming messages you can simply do
var onmessageCallbackSpy = jasmine.createSpy('onmessageCallback');
You can also spy on .send
method, and provide some mocked responses with:
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");
});
But make sure to use WebSocket.prototype
, before you replace it with WebSocketSpy
.
So full working example, should look like this:
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();
});