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

如何用Sinon模拟MongoDB Update错误?测试代码无效求助

Fixing Mongoskin Integration Test for Database Error Scenarios

Let me walk you through what's likely going wrong with your test and how to fix it to properly trigger the error branch in your route handler.

The Core Issue

Your current test tries to stub db.collection, but there's a good chance the db instance you're stubbing in your test isn't the same one your route handler is actually using. When you import db via tc.__get__('db'), you might be getting a reference that doesn't sync with the live instance in your Express route.

Step-by-Step Fixed Test Code

Here's an adjusted version of your test that ensures the stubbed database methods are properly hooked into your business code, plus adds assertions to verify the error branch runs:

var sinon = require('sinon');
var rewire = require('rewire');
var supertest = require('supertest'); // Supertest is better for Express route testing than superagent
var tc = rewire('./file');
var app = require('./your-express-app-file'); // Import your main Express app here

// Get references to internal modules in your business code
var logger = tc.__get__('logger');

describe('POST /test', () => {
  let originalDb;
  let loggerErrorSpy;

  beforeEach(() => {
    // Save the original DB reference to restore later
    originalDb = tc.__get__('db');
    // Spy on logger.error to verify it gets called
    loggerErrorSpy = sinon.spy(logger, 'error');
  });

  afterEach(() => {
    // Clean up stubs/spies after each test
    loggerErrorSpy.restore();
    tc.__set__('db', originalDb);
  });

  it('should log an error when MongoDB update fails', (done) => {
    // 1. Create a stub for the update method that yields an error
    const updateStub = sinon.stub().yields(new Error('MongoDB update failure'));
    
    // 2. Create a stub for db.collection that returns our stubbed collection
    const collectionStub = sinon.stub().returns({ update: updateStub });
    
    // 3. Replace the DB instance in your business code with our stubbed version
    tc.__set__('db', { collection: collectionStub });

    // 4. Send the POST request to your route
    supertest(app)
      .post('/test')
      .send({ /* Your test payload here */ })
      .end((err, res) => {
        // 5. Verify all our expectations are met
        sinon.assert.calledOnce(collectionStub);
        sinon.assert.calledWith(collectionStub, 'test');
        sinon.assert.calledOnce(updateStub);
        sinon.assert.calledOnce(loggerErrorSpy);
        sinon.assert.calledWith(loggerErrorSpy, sinon.match.instanceOf(Error));

        done();
      });
  });
});

Key Fixes & Explanations

  1. Use Supertest Instead of Superagent: Supertest integrates directly with your Express app, so you don't need to run a separate server for testing—it's more reliable and simpler for route testing.
  2. Rewrite the DB Instance: Using rewire.__set__ replaces the db variable in your business code entirely, ensuring your route handler uses our stubbed version instead of the original from ./setting.
  3. Add Assertions for Logger: The spy on logger.error proves the error branch was actually triggered, instead of just assuming the request completed.
  4. Clean Up Stubs: The beforeEach/afterEach blocks ensure no test pollution—stubs are reset between test runs.

Additional Notes

If your business code caches the collection at the module level (like var collection = db.collection('test') at the top of the file), you'll need to re-set that cached collection after stubbing the DB:

// After setting up the stubbed db
tc.__set__('collection', tc.__get__('db').collection('test'));

This ensures the cached collection uses your stubbed update method.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:30:55