首页 > 解决方案 > 如果依赖项已经加载,Sinon 存根不会改变行为

问题描述

进程.js

const { getConnection, closeConnection } = require('./utils/db-connection.js');

const getQueryCount = query => new Promise((resolve, rejects) => {
  getConnection().then((conn) => {
    conn.query(query, (err, count) => {
      closeConnection(conn);
      if (err) {
        log.info(`Get Count Error:  ${err}`);
        return rejects(err);
      }
      return resolve(count[0][1]);
    });
  });
});

process.test.js

const dbConn = require('../src/utils/db-connection.js');
describe('all count', () => {
    beforeEach(() => {
      sinon.stub(dbConn, 'getConnection').resolves({ query: sinon.stub().yields(null, [[0, 5]]) });
      sinon.stub(dbConn, 'closeConnection');
  const process = require('./src/process'); //module is loaded after dependencies are stubbed

    });

    it('getQueryCount', () => {
      process.getQueryCount('query').then((result) => {
        expect(result).to.equal(5);
      });
    });
  });

在上述场景中,存根有效,但抛出模块没有自注册。下面的场景存根不起作用。

process.test.js

  const dbConn = require('../src/utils/db-connection.js');
      const process = require('./src/process'); // test file is loaded at the starting
    describe('all count', () => {
        beforeEach(() => {
          sinon.stub(dbConn, 'getConnection').resolves({ query: sinon.stub().yields(null, [[0, 5]]) });
          sinon.stub(dbConn, 'closeConnection');
    
        });
    
        it('getQueryCount', () => {
          process.getQueryCount('query').then((result) => {
            expect(result).to.equal(5);
          });
        });
      });

"sinon": "9.0.2" "mocha": "^3.4.2", //甚至用 mocha 7.0.1 node --version v8.11.3 npm --v 6.2.0 检查

标签: node.jsunit-testingmocha.jssinon

解决方案


为了使存根工作,您需要将process.js上的实现从使用解构赋值更改为正常赋值。

const { getConnection, closeConnection } = require('./utils/db-connection.js');

例如

const db = require('./utils/db-connection.js');

完整示例:

// Simplified process.js
const db = require('./db-connection.js');

const getQueryCount = (query) => new Promise((resolve, rejects) => {
  // Called using db.getConnection.
  db.getConnection().then((conn) => {
    conn.query(query, (err, count) => {
      // Called using db.closeConnection.
      db.closeConnection(conn);
      if (err) {
        return rejects(err);
      }
      return resolve(count[0][1]);
    });
  });
});

module.exports = { getQueryCount };
const sinon = require('sinon');
const { expect } = require('chai');

// Simple path just for example.
const dbConn = require('./db-connection.js');
const process = require('./process.js');

describe('all count', function () {
  let stubGetConnection;
  let stubCloseConnection;

  beforeEach(function () {
    stubGetConnection = sinon.stub(dbConn, 'getConnection').resolves({ query: sinon.stub().yields(null, [[0, 5]]) });
    stubCloseConnection = sinon.stub(dbConn, 'closeConnection');
  });

  it('getQueryCount', function (done) {
    process.getQueryCount('query').then((result) => {
      expect(result).to.equal(5);
      // Need to verify whether stub get called once.
      expect(stubGetConnection.calledOnce).to.equal(true);
      expect(stubCloseConnection.calledOnce).to.equal(true);
      // Need to notify mocha when it is done.
      done();
    });
  });
});

注意:我在那里使用 done 因为它是一个异步代码

$ npx mocha process.test.js --exit


  all count
    ✓ getQueryCount


  1 passing (17ms)

$

推荐阅读