Mocha before()无法监听Express服务器的事件发射器问题
解决Mocha测试在Express服务器加载完成前执行的问题
我帮你梳理下这个问题的解决方案,其实核心就是让Mocha等待你的Express服务器完全启动并发出信号后再执行测试,刚好你已经想到了用事件发射的思路,咱们把这个逻辑补全就行:
1. 完善app.js中的事件发射逻辑
你已经写了部分服务器启动的代码,只需要在服务器成功监听端口的回调里发射一个自定义事件,同时把httpServer导出供测试文件引用:
const express = require('express'); let app = express(); app.use(require('./controllers')); const port = 8080; const httpServer = require('http').createServer(app); httpServer.listen(port, function() { console.log(`Server running on port ${port}`); // 发射服务器就绪的自定义事件 httpServer.emit('serverReady'); }); // 将httpServer导出,让测试文件可以监听它的事件 module.exports = httpServer;
2. 在测试文件中监听事件,让Mocha等待服务器就绪
Mocha提供了before钩子来处理测试前的异步准备工作,我们可以在这个钩子里面监听服务器的serverReady事件,确认服务器完全启动后再触发测试执行:
const httpServer = require('../app'); const chai = require('chai'); const expect = chai.expect; const request = require('superagent'); // 等待服务器就绪后再启动测试 before((done) => { httpServer.on('serverReady', () => { console.log('服务器已准备完毕,开始执行测试'); done(); // 调用done告诉Mocha前置准备完成,可以开始测试 }); }); // 测试完成后关闭服务器,避免端口占用 after((done) => { httpServer.close(done); }); describe('Express 服务器测试', () => { it('应该正常响应GET请求', (done) => { request.get('http://localhost:8080') .end((err, res) => { expect(res.status).to.equal(200); done(); }); }); });
额外注意事项
- 不要在测试文件里重新创建服务器实例,一定要导入app.js中导出的
httpServer,否则会启动两个独立的服务器,导致端口冲突或者事件监听失效 - 如果你使用
supertest库的话,其实它可以自动处理服务器的启动和关闭,但如果你的场景需要自定义就绪逻辑(比如等待数据库连接完成再触发测试),这种事件发射的方式会更灵活
内容的提问来源于stack exchange,提问作者Yu Chen
相关产品推荐
相关产品推荐

