【问题标题】:Mocha testing socketio middleware won't finish suiteMocha 测试 socketio 中间件不会完成套件
【发布时间】:2017-11-03 11:23:43
【问题描述】:

我正在使用 mocha 在 nodejs 8.9 上测试带有服务器和客户端组件的 nodejs-app。

为了让 mocha 正确结束,我必须确保在运行测试后关闭所有 socketio 和 http-servers。这适用于普通测试,但是一旦我向 socketio-server 注册了一个中间件,mocha 进程就不会关闭并永远保持打开状态。

测试代码(在第二个测试中评论以查看问题,通过mocha test.spec.js运行):

// test.spec.js
'use strict'

const Express = require('express')
const Http = require('http')
const ioserver = require('socket.io')
const ioclient = require('socket.io-client')

const NODE_PORT = process.env.NODE_PORT || 3000

describe('Client', function () {
    beforeEach(() => {
        const express = new Express()
        this._http = Http.Server(express)
        this._ioserver = ioserver(this._http)
        this._http.listen(NODE_PORT)
    })

    // this test works perfectly, even when I copy it and run it
    // multiple times in this suite
    it('should connect to a socketio-server', (done) => {
        this._ioserver.on('connection', () => {
            client.close()
            done()
        })
        const client = ioclient.connect(`http://localhost:${NODE_PORT}`)
    })

    // this test also finished, but the suite hangs afterwards - as if
    // a socket-client or socket-server was not closed properly.
    it('should finish the test suite even with a middleware', (done) => {
        this._ioserver.use((socket, next) => {
            return next()
        })

        this._ioserver.on('connection', () => {
            client.close()
            done()
        })

        const client = ioclient.connect(`http://localhost:${NODE_PORT}`)
    })

    afterEach(() => {
        this._ioserver.close()
        this._http.close()
    })
})

你知道为什么会这样吗?

【问题讨论】:

  • 我使用client.disconnect() 而不是close() 也许这就是原因。
  • 这两个是同义词,调用相同的方法
  • 打开了一个错误报告:github.com/mochajs/mocha/issues/3095

标签: node.js socket.io mocha.js middleware


【解决方案1】:

所以,问题在于,服务器在成功连接事件时关闭了客户端连接。客户端没有获得任何相关信息,而是看到连接失败并尝试重新连接。这再次打开了一个到服务器的套接字,并且由于服务器已经关闭,连接错误不断出现。

此行为阻止节点正确销毁所有对象,这反过来解释了挂起。解决方案是仅在 client 声明连接打开后调用done() 在服务器声明连接打开后调用,如下所示:

'use strict'

const Express = require('express')
const Http = require('http')
const ioserver = require('socket.io')
const ioclient = require('socket.io-client')

const NODE_PORT = process.env.NODE_PORT || 3000

describe('Client', function () {
    beforeEach(() => {
        const express = new Express()
        this._http = Http.Server(express)
        this._ioserver = ioserver(this._http)
        this._http.listen(NODE_PORT)
        this._client = null
    })

    it('should connect to a socketio-server', (done) => {
        this._ioserver.on('connection', () => {
            done()
        })

        this._client = ioclient.connect(`http://localhost:${NODE_PORT}`)
    })

    it('should finish the test suite even with a middleware', (done) => {
        this._ioserver.use((socket, next) => {
            return next()
        })

        this._client = ioclient.connect(`http://localhost:${NODE_PORT}`)

        // if we wait for the server and kill the server socket,
        // the client will try to reconnect and won't be killed
        // by mocha.
        this._client.on('connect', () => {
            done()
        })
    })

    afterEach(() => {
        // this last call forces the client to stop connecting
        // even if tests failed
        this._client.close()

        this._ioserver.close()
        this._http.close()
    })
})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-15
    • 2017-06-08
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-25
    相关资源
    最近更新 更多