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

如何用Mocha/Chai测试Mongoose CRUD操作?交易处理函数测试遇数据库调用未执行问题

如何使用Mocha/Chai测试Mongoose的CRUD操作?

先搞定环境与测试前置准备

首先得把依赖装齐,推荐用内存数据库测试,避免污染真实数据:

npm install mocha chai mongoose mongodb-memory-server --save-dev

然后用Mocha的钩子做测试前后的数据库管理,保证每次测试都是干净的环境:

const mongoose = require('mongoose');
const { MongoMemoryServer } = require('mongodb-memory-server');
const { expect } = require('chai');

let mongoServer;

// 测试前启动内存数据库并连接
before(async () => {
  mongoServer = await MongoMemoryServer.create();
  await mongoose.connect(mongoServer.getUri());
});

// 测试完成后断开连接并关闭内存数据库
after(async () => {
  await mongoose.disconnect();
  await mongoServer.stop();
});

// 每个测试用例前清空目标集合
beforeEach(async () => {
  await mongoose.connection.collection('users').deleteMany({});
});

逐个写CRUD的测试用例

假设你有个User模型:

const userSchema = new mongoose.Schema({
  name: String,
  email: { type: String, unique: true }
});
const User = mongoose.model('User', userSchema);

测试Create(创建)

describe('User CRUD 测试', () => {
  it('应该能创建一个新用户', async () => {
    const user = new User({ name: 'Alice', email: 'alice@test.com' });
    const savedUser = await user.save();
    
    expect(savedUser._id).to.exist;
    expect(savedUser.name).to.equal('Alice');
    expect(savedUser.email).to.equal('alice@test.com');
  });
});

测试Read(读取)

it('应该能通过邮箱找到用户', async () => {
  await User.create({ name: 'Bob', email: 'bob@test.com' });
  const foundUser = await User.findOne({ email: 'bob@test.com' });
  
  expect(foundUser).to.not.be.null;
  expect(foundUser.name).to.equal('Bob');
});

测试Update(更新)

it('应该能更新用户的名字', async () => {
  const user = await User.create({ name: 'Charlie', email: 'charlie@test.com' });
  await User.updateOne({ _id: user._id }, { name: 'Charlie Brown' });
  
  const updatedUser = await User.findById(user._id);
  expect(updatedUser.name).to.equal('Charlie Brown');
});

测试Delete(删除)

it('应该能删除指定用户', async () => {
  const user = await User.create({ name: 'Dave', email: 'dave@test.com' });
  await User.deleteOne({ _id: user._id });
  
  const deletedUser = await User.findById(user._id);
  expect(deletedUser).to.be.null;
});

测试交易处理函数时数据库调用未执行的排查与解决

从你描述的情况来看,函数本身和其他测试都正常,但这个交易处理逻辑里的数据库操作没跑起来,大概率是异步处理没做好,或者测试环境的细节没注意到,咱们一步步排查:

1. 先检查测试是否正确等待异步操作完成

你的交易处理函数肯定是异步的(涉及数据库和API调用),如果测试里没等它执行完就结束,Mocha会直接跳过异步逻辑。比如:

// 错误示例:没处理异步,测试直接结束
it('应该处理未完成的交易', () => {
  processTransactions(getPrices()); // 这个函数是异步的,但测试没等它
});

改成async/await或者返回Promise:

// 正确示例:等待异步函数执行完成
it('应该处理未完成的交易', async () => {
  // 先插入测试用的未完成交易
  await Transaction.create([
    { status: 'pending', price: 100, traderId: '123' },
    { status: 'pending', price: 200, traderId: '456' }
  ]);
  
  // 模拟API返回的价格数组
  const mockPrices = [100, 200];
  
  // 等待交易处理函数执行完毕
  await processTransactions(mockPrices);
  
  // 验证数据库变化:检查交易是否平仓、余额是否更新
  const closedTransactions = await Transaction.find({ status: 'closed' });
  expect(closedTransactions.length).to.equal(2);
  
  const trader = await Trader.findById('123');
  expect(trader.balance).to.be.greaterThan(0);
});

2. 检查API调用函数的Mock是否正确

你说这个函数依赖另一个API调用函数的返回值,如果Mock这个API函数时没正确处理异步,会导致交易逻辑提前终止。比如:

// 错误示例:Mock的API函数没返回Promise
const getPrices = () => [100, 200];

// 正确示例:Mock异步API函数
const getPrices = async () => [100, 200];
// 或者用sinon工具Mock
const sinon = require('sinon');
sinon.stub(apiModule, 'getPrices').resolves([100, 200]);

3. 排查数据库操作是否被吞了错误或未提交事务

如果你的处理函数用了Mongoose事务,或者有try/catch但没抛出错误,可能导致数据库操作没执行就结束:

// 错误示例:忘记提交事务,或者吞了错误
async function processTransactions(prices) {
  try {
    const session = await mongoose.startSession();
    session.startTransaction();
    
    const pendingTransactions = await Transaction.find({ status: 'pending' }).session(session);
    // ...处理匹配逻辑
    
    // 忘记提交事务!
    // await session.commitTransaction();
  } catch (err) {
    // 没抛出错误,测试里看不到问题
    console.log(err);
  }
}

解决办法:确保事务正确提交,并且在catch里抛出错误,或者在测试里捕获错误验证。

4. 加日志定位哪一步出问题

如果还是找不到原因,在交易处理函数的关键步骤加日志:

async function processTransactions(prices) {
  console.log('开始处理未完成交易');
  const pendingTransactions = await Transaction.find({ status: 'pending' });
  console.log(`找到 ${pendingTransactions.length} 条未完成交易`);
  
  for (const tx of pendingTransactions) {
    console.log(`处理交易 ${tx._id},价格:${tx.price}`);
    // ...匹配价格、平仓、更新余额的逻辑
  }
}

运行测试时看日志,就能知道是哪一步没执行,快速定位问题。

内容的提问来源于stack exchange,提问作者burningserenity

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:38:57