You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何重构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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 15:53:00