如何重构Express项目的index.js,避免运行测试时触发数据库连接
如何重构Express项目的index.js,避免运行测试时触发数据库连接
我之前做Express+Mocha测试的时候也踩过这个坑,核心问题就是当前的index.js把Express应用的配置和服务启动、数据库连接耦合在一起了,导致导入app的时候会自动执行所有代码。解决思路很简单——把这两部分拆分开,测试时只加载配置好的app实例,不触发启动逻辑。
第一步:拆分应用配置与启动逻辑
我们可以把创建和配置Express app的代码单独抽成一个文件,比如app.js,而原来的index.js只作为服务的入口,负责启动服务和连接数据库。
1. 新建src/app.js(根据你的项目结构调整路径)
把原来index.js里除了数据库连接、app.listen之外的代码移到这里,只保留app的初始化、中间件和路由配置:
require('./Models/UsersModel'); const express = require('express'); require('dotenv').config(); const bodyParser = require('body-parser'); const authRoutes = require('./routes/authRoutes'); const requireAuth = require('./middlewares/requireAuth'); // 注意路径修正,原来的../src可能是笔误,根据实际结构调整 // 创建Express实例并配置 const app = express(); app.use(bodyParser.json()); app.use(authRoutes); // 根路由 app.get('/', requireAuth, (req, res) => { res.send(`${req.user.email}`); }); // 导出app供其他模块(比如测试、入口文件)使用 module.exports = app;
2. 修改原src/index.js作为服务入口
现在index.js只负责数据库连接和启动服务,导入上面的app实例即可:
const app = require('./app'); const mongoose = require('mongoose'); // 注意PORT的顺序,应该优先用环境变量 const PORT = process.env.PORT || 3000; const MONGO_URI = process.env.MONGO_URI; // 数据库连接逻辑 mongoose.connect(MONGO_URI, {}) mongoose.connection.on('connected', () => { console.log('connected to dev-cluster'); }); mongoose.connection.on('error', (err) => { console.log('error connecting to dev-cluster'); console.log(err); }); // 只有非测试环境才启动服务监听 if (process.env.NODE_ENV !== 'test') { app.listen(PORT, () => { console.log(`app started on port:${PORT}`); }); }
3. 调整测试文件的导入路径
原来的测试文件导入的是../src/index,现在改成导入拆分后的app.js,这样测试时只会加载配置好的app,不会触发数据库连接和服务启动:
const request = require('supertest'); const app = require('../src/app'); // 替换为app.js的路径 describe('Authentication Routes', () => { it('POST /login should respond with 200 and user data', async () => { const response = await request(app) .post('/login') .send({ username: 'testuser', password: 'testpass' }); expect(response.statusCode).toBe(200); expect(response.body).toHaveProperty('user'); }); it('POST /register should respond with 201 and user data', async () => { const response = await request(app) .post('/register') .send({ username: 'newuser', password: 'newpass' }); expect(response.statusCode).toBe(201); expect(response.body).toHaveProperty('user'); }); it('GET /logout should respond with 200', async () => { const response = await request(app).get('/logout'); expect(response.statusCode).toBe(200); }); });
第二步:额外的测试优化建议
为了让测试更可靠,还可以做这些优化:
使用独立的测试数据库:在
.env里新增TEST_MONGO_URI,指向专门的测试数据库,避免测试数据污染开发库。可以通过NODE_ENV区分环境,比如在package.json的测试脚本里设置:"scripts": { "start": "node src/index.js", "test": "NODE_ENV=test mocha" }然后在数据库连接逻辑里判断环境:
const MONGO_URI = process.env.NODE_ENV === 'test' ? process.env.TEST_MONGO_URI : process.env.MONGO_URI;用内存数据库提升测试速度:可以用
mongodb-memory-server,它会在内存中临时启动MongoDB实例,测试结束自动销毁,不需要提前搭建数据库。安装后在测试的全局钩子中配置:const { MongoMemoryServer } = require('mongodb-memory-server'); const mongoose = require('mongoose'); let mongoServer; // 测试前启动内存数据库并连接 before(async () => { mongoServer = await MongoMemoryServer.create(); await mongoose.connect(mongoServer.getUri()); }); // 测试后断开连接并停止内存数据库 after(async () => { await mongoose.disconnect(); await mongoServer.stop(); });测试时禁用不必要的日志:比如数据库连接的日志,可以在测试环境下关闭,避免干扰测试输出。
备注:内容来源于stack exchange,提问作者Kpizzle
相关产品推荐
相关产品推荐

