【问题标题】:Unit test Mysql without connecting to database with NodeJS在不使用 NodeJS 连接数据库的情况下对 Mysql 进行单元测试
【发布时间】:2021-01-14 15:08:03
【问题描述】:

我有一个 Conn 类,用于使用 AWS IAM 身份验证连接到 MySQL 数据库并运行查询。我已经编写了课程并且它工作正常,但是我在尝试在不访问数据库的情况下对其进行测试时遇到了很多困难。

这是 Conn 类:

const AWS = require('aws-sdk');
const mysql = require("mysql2/promise");

class Conn {
    constructor(options = {}) {
        this.options = options;
    }

    async getPool() {
        return mysql.createPool(this.options);
    }

    setToken () {
        this.signer = new AWS.RDS.Signer({
            region: 'us-east-1', // example: us-east-2
            hostname: this.options.host,
            port: 3306,
            username: this.options.user
        });

        this.token = this.signer.getAuthToken({
            username: this.options.user
        });
    }

    async setConnection () {
        this.dbOptions = {
            host     : this.options.host,
            user     : this.options.user,
            ssl: 'Amazon RDS',
            password: this.token,
            authPlugins: {
                mysql_clear_password: () => () => Buffer.from(this.token + '\0')
            }
        };

        this.pool = await this.getPool(this.dbOptions);
        this.conn = await this.pool.getConnection();
    }

    async executeQuery () {
        this.dbResult = await this.conn.query("select 1 + 1 as solution");
        this.conn.release();
    }
}

module.exports = {
    Conn: Conn
}

我在这里尝试使用 sinon 测试 Conn.executeQuery 函数:

const { handler } = require("../src/conn");
const sinon = require("sinon");
const {expect: expects} = require("chai");
const connection = require('../src/conn');

describe("conn", () => {
    afterEach(() => {
        sinon.restore();
    });
    it("should test conn.executeQuery", async () => {
        const connStub = { query: sinon.stub().resolves({ rowCount: 1 }), release: sinon.stub() };
        const poolStub = { getConnection: sinon.stub().resolves(connStub) };
        const pool = {getPool: sinon.stub().resolves(poolStub)};
        const conn = new connection.Conn();
        await conn.setConnection();
        const actual = await conn.executeQuery()
        expects(actual).to.be.eql({ rowCount: 1 });
        sinon.assert.calledWith(connStub.query, "select 1 + 1 as solution");
        sinon.assert.calledOnce(connStub.release);
    });
});

不幸的是,这段代码产生的只是错误,例如

错误:连接 ECONNREFUSED 127.0.0.1:3306

如何使用sinon 测试Conn.executeQuery 函数而不命中数据库?

【问题讨论】:

    标签: mysql node.js aws-lambda chai sinon


    【解决方案1】:

    单元测试解决方案:

    Conn.js:

    const mysql = require('mysql2/promise');
    
    class Conn {
      constructor(options = {}) {
        this.options = options;
      }
    
      async getPool() {
        return mysql.createPool(this.options);
      }
    
      async setConnection() {
        this.dbOptions = {
          host: this.options.host,
          user: this.options.user,
          ssl: 'Amazon RDS',
          password: this.token,
          authPlugins: {
            mysql_clear_password: () => () => Buffer.from(this.token + '\0'),
          },
        };
    
        this.pool = await this.getPool(this.dbOptions);
        this.conn = await this.pool.getConnection();
      }
    
      async executeQuery() {
        this.dbResult = await this.conn.query('select 1 + 1 as solution');
        this.conn.release();
      }
    }
    
    module.exports = { Conn };
    

    Conn.test.js:

    const { Conn } = require('./Conn');
    const sinon = require('sinon');
    const mysql = require('mysql2/promise');
    
    describe('64112250', () => {
      afterEach(() => {
        sinon.restore();
      });
      it('should test conn.executeQuery', async () => {
        const poolStub = {
          getConnection: sinon.stub().returnsThis(),
          query: sinon.stub().returnsThis(),
          release: sinon.stub(),
        };
        const createPoolStub = sinon.stub(mysql, 'createPool').returns(poolStub);
        const conn = new Conn();
        await conn.setConnection();
        await conn.executeQuery();
        sinon.assert.calledOnce(createPoolStub);
        sinon.assert.calledOnce(poolStub.getConnection);
        sinon.assert.calledWithExactly(poolStub.query, 'select 1 + 1 as solution');
        sinon.assert.calledOnce(poolStub.release);
      });
    });
    

    带有覆盖率报告的单元测试结果:

      64112250
        ✓ should test conn.executeQuery
    
    
      1 passing (24ms)
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |   81.82 |      100 |   66.67 |      90 |                   
     Conn.js  |   81.82 |      100 |   66.67 |      90 | 19                
    ----------|---------|----------|---------|---------|-------------------
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-22
      • 2020-04-29
      相关资源
      最近更新 更多