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

如何使用Mocha、Chai与Sinon模拟sequelizeConnector、mongoConnector返回结果

解决方案

你可以通过proxyquire替换模块依赖,配合Sinon打桩来完全mock掉两个数据库连接工具的实现,完全避免触发真实数据库连接,同时还可以验证这两个连接器是否被正确调用。


步骤1:安装依赖

如果还没装proxyquire的话先安装:

npm install proxyquire --save-dev

步骤2:修改测试代码

完整测试代码如下:

const chai = require("chai");
const sinon = require("sinon");
const sinonChai = require("sinon-chai");
const proxyquire = require("proxyquire");
const express = require("express");

const { expect } = chai;
chai.should();
chai.use(sinonChai);

describe("CreateServer", () => {
  // 预先声明要mock的依赖
  let mockSequelizeConnector;
  let mockMongoConnector;
  let mockLogger;
  let mockDatabases;
  let CreateServer;

  beforeEach(() => {
    // 初始化所有stub
    mockSequelizeConnector = sinon.stub();
    mockMongoConnector = sinon.stub().returns(sinon.stub()); // 模拟返回中间件函数
    mockLogger = {
      info: sinon.stub(),
      error: sinon.stub()
    };
    mockDatabases = {
      sequelizeSupportDialect: ["mysql", "postgres", "mariadb", "mssql"],
      mongodbDialect: "mongodb"
    };

    // 用proxyquire替换createServer中的依赖
    CreateServer = proxyquire("./createServer", {
      "./sequelizeConnector": mockSequelizeConnector,
      "./mongoConnector": mockMongoConnector,
      "custom-error-exceptions": {
        logger: { logger: mockLogger }
      },
      // 对应mock原代码用到的databases常量,如果是从其他模块引入就改对应引入路径
      "databases": mockDatabases
    });

    // mock express实例的use方法方便后续验证
    sinon.stub(express, "express").returns({
      use: sinon.stub()
    });
  });

  afterEach(() => {
    // 每次测试后清空stub,避免用例互相影响
    sinon.restore();
  });

  describe("choosingDatabase", () => {
    it("无数据库配置时打印对应日志", () => {
      const server = new CreateServer({});
      server.choosingDatabase();
      expect(mockLogger.info).to.have.been.calledWith("No database config found");
    });

    it("传入支持的sequelize方言时调用sequelizeConnector", () => {
      const testConfig = {
        dbConfig: { dialect: "mysql" }
      };
      const testModels = { user: {} };
      const server = new CreateServer({ config: testConfig, models: testModels });
      
      server.choosingDatabase();
      
      expect(mockLogger.info).to.have.been.calledWith("Using sequelize dialect mysql database");
      expect(mockSequelizeConnector).to.have.been.calledOnceWith(
        server.app,
        testConfig,
        mockLogger,
        testModels
      );
    });

    it("传入mongodb方言时调用mongoConnector并注册中间件", () => {
      const testConfig = {
        dbConfig: { dialect: "mongodb" }
      };
      const testModels = { goods: {} };
      const server = new CreateServer({ config: testConfig, models: testModels });
      const mockMiddleware = mockMongoConnector.returnValues[0];
      
      server.choosingDatabase();
      
      expect(mockLogger.info).to.have.been.calledWith("Using mongodb database");
      expect(mockMongoConnector).to.have.been.calledOnceWith(
        server.app,
        testConfig,
        mockLogger,
        testModels
      );
      expect(server.app.use).to.have.been.calledOnceWith(mockMiddleware);
    });

    it("传入不支持的方言时打印错误日志", () => {
      const testConfig = {
        dbConfig: { dialect: "wrong" }
      };
      const server = new CreateServer({ config: testConfig });
      
      server.choosingDatabase();
      
      expect(mockLogger.error).to.have.been.calledWith("Dialect you're choosing ins'nt supported");
    });
  });
})

关键说明

  • 用proxyquire可以在加载createServer.js的时候,直接替换它引入的外部依赖模块,不需要修改原业务代码
  • 所有外部依赖(logger、databases常量、两个连接器)都被mock成了Sinon stub,不会执行真实的连接逻辑
  • 原测试中的三个用例逻辑重复,仅验证了方法被调用,上述代码已经覆盖了四个分支,同时验证了入参、日志、后续调用逻辑是否正确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 11:36:06