任何人都可以提供的Node.js使用的WebSockets(Socket.io)坚如磐石的,死简单的单元测试?
我使用socket.io于Node.js,并看着socket.io客户端建立测试客户端连接到服务器。 但是,我似乎失去了一些东西。
在下面的例子中,“工作......”永远不会被打印出来。
var io = require('socket.io-client')
, assert = require('assert')
, expect = require('expect.js');
describe('Suite of unit tests', function() {
describe('First (hopefully useful) test', function() {
var socket = io.connect('http://localhost:3001');
socket.on('connect', function(done) {
console.log('worked...');
done();
});
it('Doing some things with indexOf()', function() {
expect([1, 2, 3].indexOf(5)).to.be.equal(-1);
expect([1, 2, 3].indexOf(0)).to.be.equal(-1);
});
});
});
相反,我只是得到:
Suite of unit tests
First (hopefully useful) test
✓ Doing some things with indexOf()
1 test complete (26 ms)
有什么建议?
Answer 1:
进一步戳和打回原形后,我发现了一些非常有用的信息http://blog.foundry376.com/2012/09/connecting-to-a-socket-io-server-from-node-js-unit-tests 。 在笔者的例子,他指出,在“*前”挂钩建立套接字监听的关键步骤。 这个例子工程(假设服务器监听本地主机的套接字连接:3001,当然)
var io = require('socket.io-client')
, assert = require('assert')
, expect = require('expect.js');
describe('Suite of unit tests', function() {
var socket;
beforeEach(function(done) {
// Setup
socket = io.connect('http://localhost:3001', {
'reconnection delay' : 0
, 'reopen delay' : 0
, 'force new connection' : true
});
socket.on('connect', function() {
console.log('worked...');
done();
});
socket.on('disconnect', function() {
console.log('disconnected...');
})
});
afterEach(function(done) {
// Cleanup
if(socket.connected) {
console.log('disconnecting...');
socket.disconnect();
} else {
// There will not be a connection unless you have done() in beforeEach, socket.on('connect'...)
console.log('no connection to break...');
}
done();
});
describe('First (hopefully useful) test', function() {
it('Doing some things with indexOf()', function(done) {
expect([1, 2, 3].indexOf(5)).to.be.equal(-1);
expect([1, 2, 3].indexOf(0)).to.be.equal(-1);
done();
});
it('Doing something else with indexOf()', function(done) {
expect([1, 2, 3].indexOf(5)).to.be.equal(-1);
expect([1, 2, 3].indexOf(0)).to.be.equal(-1);
done();
});
});
});
我发现,()完成在beforeEach,socket.on(“连接” ...)监听器的位置是具有连接得到建立至关重要。 例如,如果您注释掉()完成的监听器,然后将其添加一个范围之(刚出beforeEach之前),你会看到“没有连接,打破......”消息,而不是“断开.. 。“ 信息。 像这样:
beforeEach(function(done) {
// Setup
socket = io.connect('http://localhost:3001', {
'reconnection delay' : 0
, 'reopen delay' : 0
, 'force new connection' : true
});
socket.on('connect', function() {
console.log('worked...');
//done();
});
socket.on('disconnect', function() {
console.log('disconnected...');
});
done();
});
我是新来的摩卡,所以大概有一个很明显的原因,以发起用于放置完成的()withiin插座范围本身。 希望这小小的细节会在我的鞋救其他人的头发拉。
对我来说,上面的测试(用()完成的正确范围界定)输出:
Suite of unit tests
First (hopefully useful) test
◦ Doing some things with indexOf(): worked...
✓ Doing some things with indexOf()
disconnecting...
disconnected...
◦ Doing something else with indexOf(): worked...
✓ Doing something else with indexOf()
disconnecting...
disconnected...
2 tests complete (93 ms)
Answer 2:
这里提供的接受的答案的延伸。 有基本的客户作为样板其他以后的测试中有用的服务器进行通信。 采用摩卡,薛宝钗,并期望。
var io = require('socket.io-client')
, io_server = require('socket.io').listen(3001);
describe('basic socket.io example', function() {
var socket;
beforeEach(function(done) {
// Setup
socket = io.connect('http://localhost:3001', {
'reconnection delay' : 0
, 'reopen delay' : 0
, 'force new connection' : true
, transports: ['websocket']
});
socket.on('connect', () => {
done();
});
socket.on('disconnect', () => {
// console.log('disconnected...');
});
});
afterEach((done) => {
// Cleanup
if(socket.connected) {
socket.disconnect();
}
io_server.close();
done();
});
it('should communicate', (done) => {
// once connected, emit Hello World
io_server.emit('echo', 'Hello World');
socket.once('echo', (message) => {
// Check that the message matches
expect(message).to.equal('Hello World');
done();
});
io_server.on('connection', (socket) => {
expect(socket).to.not.be.null;
});
});
});
Answer 3:
我有这个问题:如何做单元测试与“socket.io客户”,如果你不知道服务器需要多长时间响应?
我已经解决了所以用摩卡和薛宝钗 :
var os = require('os');
var should = require("chai").should();
var socketio_client = require('socket.io-client');
var end_point = 'http://' + os.hostname() + ':8081';
var opts = {forceNew: true};
describe("async test with socket.io", function () {
this.timeout(10000);
it('Response should be an object', function (done) {
setTimeout(function () {
var socket_client = socketio_client(end_point, opts);
socket_client.emit('event', 'ABCDEF');
socket_client.on('event response', function (data) {
data.should.be.an('object');
socket_client.disconnect();
done();
});
socket_client.on('event response error', function (data) {
console.error(data);
socket_client.disconnect();
done();
});
}, 4000);
});
});
Answer 4:
检查出是基于承诺和良好做法 ,这个样板的解决方案。 您可以测试您的服务器与它整个IO事件,无汗。 你只需要复制样板的测试,并根据需要添加自己的代码。
结帐完整的源代码在GitHub回购。
https://github.com/PatMan10/testing_socketIO_server
const io = require("socket.io-client");
const ev = require("../utils/events");
const logger = require("../utils/logger");
// initSocket returns a promise
// success: resolve a new socket object
// fail: reject a error
const initSocket = () => {
return new Promise((resolve, reject) => {
// create socket for communication
const socket = io("localhost:5000", {
"reconnection delay": 0,
"reopen delay": 0,
"force new connection": true
});
// define event handler for sucessfull connection
socket.on(ev.CONNECT, () => {
logger.info("connected");
resolve(socket);
});
// if connection takes longer than 5 seconds throw error
setTimeout(() => {
reject(new Error("Failed to connect wihtin 5 seconds."));
}, 5000);
}
);
};
// destroySocket returns a promise
// success: resolve true
// fail: resolve false
const destroySocket = socket => {
return new Promise((resolve, reject) => {
// check if socket connected
if (socket.connected) {
// disconnect socket
logger.info("disconnecting...");
socket.disconnect();
resolve(true);
} else {
// not connected
logger.info("no connection to break...");
resolve(false);
}
});
};
describe("test suit: Echo & Bello", () => {
test("test: ECHO", async () => {
// create socket for communication
const socketClient = await initSocket();
// create new promise for server response
const serverResponse = new Promise((resolve, reject) => {
// define a handler for the test event
socketClient.on(ev.res_ECHO, data4Client => {
//process data received from server
const { message } = data4Client;
logger.info("Server says: " + message);
// destroy socket after server responds
destroySocket(socketClient);
// return data for testing
resolve(data4Client);
});
// if response takes longer than 5 seconds throw error
setTimeout(() => {
reject(new Error("Failed to get reponse, connection timed out..."));
}, 5000);
});
// define data 4 server
const data4Server = { message: "CLIENT ECHO" };
// emit event with data to server
logger.info("Emitting ECHO event");
socketClient.emit(ev.com_ECHO, data4Server);
// wait for server to respond
const { status, message } = await serverResponse;
// check the response data
expect(status).toBe(200);
expect(message).toBe("SERVER ECHO");
});
test("test BELLO", async () => {
const socketClient = await initSocket();
const serverResponse = new Promise((resolve, reject) => {
socketClient.on(ev.res_BELLO, data4Client => {
const { message } = data4Client;
logger.info("Server says: " + message);
destroySocket(socketClient);
resolve(data4Client);
});
setTimeout(() => {
reject(new Error("Failed to get reponse, connection timed out..."));
}, 5000);
});
const data4Server = { message: "CLIENT BELLO" };
logger.info("Emitting BELLO event");
socketClient.emit(ev.com_BELLO, data4Server);
const { status, message } = await serverResponse;
expect(status).toBe(200);
expect(message).toBe("SERVER BELLO");
});
});
----脚注----
根据你如何设置你的服务器环境中,你可能会遇到socket.io和同时在相同的项目运行socket.io客户机之间的环境冲突。 在这种情况下,这将是更好的项目分成了“测试客户端”和服务器。 下面回购结帐,如果你得到了这个问题。
https://github.com/PatMan10/testing_socketIO_server_v2
文章来源: Unit testing Node.js and WebSockets (Socket.io)