首页 > 解决方案 > JestJS - 多个 websocket 连接挂起 Jest

问题描述

我正在使用此功能来测试我的服务器,该服务器创建尽可能多的 websocket 连接并检查我的游戏何时开始。但是,无论我分配的超时时间如何,它都会挂在 JestJS 上。在浏览器 - Firefox、Edge Chromium 上,它运行得非常好。

function checkGameStart(numberOfBots) {
    return new Promise((resolve, reject) => {
        let clients = [];
        let connection = [];
        for (let i = 0; i < numberOfBots; i++) {
            clients.push(new WebSocket('ws://127.0.0.1:8080'));
            connection.push(false);
            clients[i].onmessage = (msg) => {
                let data = JSON.parse(msg.data);
                if (data.title === "gameStarted") {
                    connection[i] = true;
                    checkAllClientsReady();
                }
            }
            clients[i].onerror = (err) => reject(err);
        }
        function checkAllClientsReady() {
            if (!(connection.includes(false))) {
                resolve(true);
                closeAllConnections();
            }
        }
        function closeAllConnections() {
            for (let i = 0; i < clients; i++) {
                clients[i].close()
            }
        }
    });
}

有谁知道它为什么会发生,我可以做些什么来确保它不会再次发生。

测试代码;

test('Check the game starts', () => {
    return expect(checkGameStart(4)).resolves.toBe(true);
});

标签: javascriptnode.jswebsocketjestjs

解决方案


我稍微重构了您的代码,并ws在测试设置中使用 NPM 包添加了一个 WebSocket 服务器:

const { WebSocketServer } = require('ws')

const port = 8080
const wss = new WebSocketServer({ port })

beforeAll(() => {
  wss.on('connection', (ws) => {
    ws.send(JSON.stringify({ title: 'gameStarted' }))
  })
})
afterAll(() => {
  wss.close()
})

async function checkGameStart(numberOfBots) {
  await Promise.all(
    new Array(numberOfBots).fill(null)
      .map(() => new Promise((resolve, reject) => {
        const ws = new WebSocket(`ws://localhost:${port}`)

        ws.onmessage = ({ data }) => {
          const { title } = JSON.parse(data)
          if (title === 'gameStarted') {
            ws.close()
            resolve()
          }
        }

        ws.onerror = (err) => {
          ws.close()
          reject(err)
        }
      }))
  )
  return true
}

test('Check the game starts', async () => {
  await expect(checkGameStart(4)).resolves.toBe(true);
});

$ npx jest
 PASS  ./websocket.test.js
  ✓ Check the game starts (64 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.708 s, estimated 1 s
Ran all test suites.

这仅在 Jest 也配置为使用jsdom测试环境时才有效:

// jest.config.js
module.exports = {
  testEnvironment: "jsdom",
};

否则,WebSocket构造函数将是undefined,因为它仅在 Web 浏览器环境中可用,并且默认情况下,Jest 在node环境中运行。


推荐阅读