用Jasmine在JavaScript中stubing WebSocket
我尝试测试消息上的用Jasmine在JavaScript中stubing WebSocket,javascript,testing,websocket,jasmine,stub,Javascript,Testing,Websocket,Jasmine,Stub,我尝试测试消息上的是否是正确的函数 下面是一个测试: describe(".init(address, window)", function() { beforeEach(function() { address = 'ws://test.address'; window = {}; e = { data: {} } spyOn(window, 'WebSocket').and.returnValue(fun
是否是正确的函数
下面是一个测试:
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);
});
});
以下是实施方案:
FL.init = function(address, window) {
if ('WebSocket' in window) {
var ws = new WebSocket(address);
ws.onmessage = function(e) {
this.handleMessage(e.data);
};
return ws;
}
};
第一次测试通过了。在第二种情况下,ws
是undefined
。为什么呢?我在控制台中尝试了new function(){return{onmessage:null}
,它看起来应该没问题。我不完全确定我是否理解了您的代码应该如何运行,但是如果您需要监视WebSocket
构造函数和存根。send
方法来模拟一些传入的消息,下面是如何实现它
要监视WebSocket
,您需要调用。和.callThrough
,而不是returnValue
。但是,它的结果是抱怨缺少new
关键字(如中所述),因此您需要伪造构造函数:
要对传入的消息进行监视,只需执行以下操作
您还可以监视.send
方法,并提供一些模拟响应,包括:
但在用WebSocketSpy
替换之前,请确保使用WebSocket.prototype
因此,完整的工作示例应如下所示:
我在模拟jasmine测试的websocket时遇到了它。下面是一个使用相当广泛的mock window.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);
});
});
var onmessageCallbackSpy = jasmine.createSpy('onmessageCallback');
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");
});
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();
});
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);
});
});