OPのコードでは、
socket.on('connect', function(done) {
console.log('worked...');
done();
});
done
間違ったコールバックに適用されました。コールバックから削除して、socket.on
Mochaのit
ブロックコールバックに追加する必要があります。
it('First (hopefully useful) test', function (done) {
var socket = io.connect('http://localhost:3001');
socket.on('connect', function () {
console.log('worked...');
done();
});
});
完全な例
既存の回答は素晴らしいですが、最終的にテストされているサーバーを示していません。console.log
これは、何が起こっているのかを説明するためのs付きの完全なバージョンです。説明は次のとおりです。
src/server.js
:
const express = require("express");
const createServer = (port=3000) => {
const app = express();
const http = require("http").Server(app);
const io = require("socket.io")(http);
io.on("connection", socket => {
console.log("[server] user connected");
socket.on("message", msg => {
console.log(`[server] received '${msg}'`);
socket.emit("message", msg);
});
socket.on("disconnect", () => {
console.log("[server] user disconnected");
});
});
http.listen(port, () =>
console.log(`[server] listening on port ${port}`)
);
return {
close: () => http.close(() =>
console.log("[server] closed")
)
};
};
module.exports = {createServer};
test/server.test.js
:
const {expect} = require("chai");
const io = require("socket.io-client");
const {createServer} = require("../src/server");
const socketUrl = "http://localhost:3000";
describe("server", function () {
this.timeout(3000);
let server;
let sockets;
beforeEach(() => {
sockets = [];
server = createServer();
});
afterEach(() => {
sockets.forEach(e => e.disconnect())
server.close();
});
const makeSocket = (id=0) => {
const socket = io.connect(socketUrl, {
"reconnection delay": 0,
"reopen delay": 0,
"force new connection": true,
transports: ["websocket"],
});
socket.on("connect", () => {
console.log(`[client ${id}] connected`);
});
socket.on("disconnect", () => {
console.log(`[client ${id}] disconnected`);
});
sockets.push(socket);
return socket;
};
it("should echo a message to a client", done => {
const socket = makeSocket();
socket.emit("message", "hello world");
socket.on("message", msg => {
console.log(`[client] received '${msg}'`);
expect(msg).to.equal("hello world");
done();
});
});
it("should echo messages to multiple clients", () => {
const sockets = [...Array(5)].map((_, i) => makeSocket(i));
return Promise.all(sockets.map((socket, id) =>
new Promise((resolve, reject) => {
const msgs = [..."abcd"].map(e => e + id);
msgs.slice().forEach(e => socket.emit("message", e));
socket.on("message", msg => {
console.log(`[client ${id}] received '${msg}'`);
expect(msg).to.equal(msgs.shift());
if (msgs.length === 0) {
resolve();
}
});
})
));
});
});
要約すると、サーバーはサーバーアプリを最初から作成できる関数をエクスポートし、各it
ブロックをべき等にし、サーバーの状態がテスト間で実行されないようにします(サーバーに永続性がないことを前提としています)。アプリを作成すると、関数を含むオブジェクトが返されますclose
。socket.disconnect()
タイムアウトを回避するために、各テストでソケットごとに呼び出す必要があります。
これらの要件を前提として、テストスイートは次のテストごとのセットアップ/ティアダウンワークフローに従います。
let server;
let sockets;
beforeEach(() => {
sockets = [];
server = createServer();
});
afterEach(() => {
sockets.forEach(e => e.disconnect())
server.close();
});
makeSocket
は、ソケットクライアントの接続と切断の繰り返しの定型文を減らすためのオプションのヘルパーです。sockets
後でクリーンアップするためにアレイに副作用が発生しますが、これはit
ブロックの観点からの実装の詳細です。他のワークフローは必要に応じて可能性がありますが、テストブロックは触れserver
たり変数を使用したりしないでください。sockets
重要なポイントは、テストケースのべき等性と、各テストケースの後にすべての接続を閉じることです。
クライアント上のオブジェクトのオプションを使用するsocket.connect
と、ソケットのトランスポートと動作を選択できます。既存のソケットを再利用する代わりに、ソケットごと"force new connection": true
に新しいものを作成し、長いポーリングからすぐにWSプロトコルにアップグレードします。Manager
transports: ["websocket"]
コールバックですべての作業が完了した後に使用it("should ... ", done => { /* tests */ });
して呼び出すdone()
か、promiseを返します(そしてコールバックdone
へのパラメーターを省略しit
ます)。上記の例は、両方のアプローチを示しています。
この投稿で使用:
node
:12.19.0
chai
:4.2.0
express
:4.16.4
mocha
:5.2.0
socket.io
:2.2.0
socket.io-client
:2.2.0