Unité de test Node.js et WebSockets (Socket.io)

Quelqu’un pourrait-il fournir un test unitaire à la fois simple et solide pour Node.js à l’aide de WebSockets (Socket.io)?

J’utilise socket.io pour Node.js et j’ai regardé socket.io-client pour établir la connexion du client à un serveur dans le test. Cependant, il me semble manquer quelque chose.

Dans l’exemple ci-dessous, “travaillé …” n’est jamais imprimé.

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

Au lieu de cela, je reçois simplement:

  Suite of unit tests First (hopefully useful) test ✓ Doing some things with indexOf() 1 test complete (26 ms) 

Aucune suggestion?

Après avoir poussé et poussé plus loin, j’ai trouvé des informations incroyablement utiles sur http://blog.foundry376.com/2012/09/connecting-to-a-socket-io-server-from-node-js-unit-tests . Dans l’exemple de l’auteur, il souligne l’étape critique consistant à établir des écouteurs de socket dans les hooks “before *”. Cet exemple fonctionne (en supposant qu’un serveur écoute les connexions de socket sur localhost: 3001, bien sûr)

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

J’ai trouvé que le placement de done () dans le listel beforeEach, socket.on (‘connect’ …) était crucial pour que la connexion soit établie. Par exemple, si vous commentez done () dans le programme d’écoute, puis ajoutez-le à une scope (juste avant de quitter la méthode beforeEach), vous verrez le message “no connection to break …” au lieu de “se déconnecter .. .” message. Ainsi:

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

Je suis nouveau sur Mocha, il y a donc probablement une raison évidente pour les initiés de placer done () dans la scope de la socket elle-même. Espérons que ce petit détail sauvera les autres dans mes chaussures de tirer les cheveux.

Pour moi, le test ci-dessus (avec une scope correcte des sorties de done ()):

  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) 

Offrant une extension de la réponse acceptée ici. La communication client / serveur de base est-elle utile pour les futurs tests. Utiliser mocha, chai et attendre.

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

J’ai eu ce problème: Comment faire un test unitaire avec un “socket.io-client” si vous ne savez pas combien de temps le serveur prend pour répondre?

J’ai donc résolu en utilisant moka et chai :

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