NestJS E2E测试中Mongoose find无法返回MongoDB文档
我采用E2E测试方案验证NestJS应用向MongoDB写入文档的数量:通过Jest对Docker中运行的应用发起HTTP请求,之后查询MongoDB文档并验证数量。但调用mongoose的find({})始终返回空数组,而MongoDB Compass显示集合中确实存在文档。
应用Schema定义
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import { Document } from 'mongoose'; export type MyDocument = MyData & Document; @Schema({timestamps: true, autoIndex:false, collection: 'my_documents'}) export class MyData { @Prop({ required: true }) message: string; } export const MySchema = SchemaFactory.createForClass(MyData);
测试代码
import { MyData, MySchema } from 'apps/api/src/app/schema'; import axios from 'axios'; import { connect, model } from 'mongoose'; import { resetDb, sleep } from '../support/helpers'; describe('Post twice, then get', () => { beforeEach(async () => { await resetDb(); // let things settle await sleep(10000); }); it('should return two messages', async () => { const deleteResult = await axios.delete('/'); expect(deleteResult.status).toBe(200); const post1 = await axios.post('/', { message: 'Hello' }); expect(post1.status).toBe(201); const post2 = await axios.post('/', { message: 'Hello2' }); expect(post2.status).toBe(201); const res = await axios.get('/'); expect(res.status).toBe(200); await connect(process.env.MONGODB_URI); const myModel = model<MyData>('MyData', MySchema); const documents = await myModel.find({}); console.log(documents); expect(documents.length).toBe(2); }); });
复现方式
基于NX monorepo创建了最小可复现项目,在仓库根目录执行命令 npx nx e2e api-e2e,该命令会自动构建并Docker化应用,通过Docker Compose启动MongoDB和应用容器。
1. 模型与集合名称不匹配
你的Schema明确指定了集合名为my_documents,但创建模型时仅传入了MyData作为模型名。Mongoose默认会将模型名转为复数小写形式作为集合名(此处会生成mydatas),导致测试代码查询的是错误集合,自然返回空数组。
解决代码:创建模型时显式指定集合名称:
const myModel = model<MyData>('MyData', MySchema, 'my_documents');
2. 数据库连接管理问题
测试用例中每次执行都调用connect建立新连接,可能存在连接未就绪、多连接冲突的情况。建议统一管理连接生命周期:
import mongoose from 'mongoose'; describe('Post twice, then get', () => { beforeAll(async () => { await mongoose.connect(process.env.MONGODB_URI); }); afterAll(async () => { await mongoose.disconnect(); }); // 其余测试代码不变 });
3. 写入操作未完成持久化
虽然HTTP请求返回201状态码,但应用端的数据库写入可能还未完成持久化。可在POST请求后增加短暂等待,或确保应用端的写入逻辑是同步完成的:
const post2 = await axios.post('/', { message: 'Hello2' }); expect(post2.status).toBe(201); await sleep(500); // 增加短暂等待
4. 环境变量数据库地址不一致
确认测试代码中process.env.MONGODB_URI与应用连接的MongoDB地址完全一致。比如应用连接的是Docker容器内的mongodb://mongo:27017/test,而测试代码可能连接的是本地mongodb://localhost:27017/test,导致查询的数据库实例不匹配。
内容的提问来源于stack exchange,提问作者dfsg76

