【问题标题】:Unit test mysql query with callback using sinon使用 sinon 对带有回调的 mysql 查询进行单元测试
【发布时间】:2021-01-20 22:23:40
【问题描述】:

我有一个类用于创建 mysql 连接池并在数据库中插入记录。插入工作正常,但我无法通过单元测试获得全面覆盖。

这是连接类:

const mysql2 = require('mysql2');

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

    createPool () {
        this.pool = mysql2.createPool({
            host: this.options.host,
            user: this.options.user,
            database:  'my_database',
            ssl: 'Amazon RDS',
            password: this.options.password,
            authPlugins: {
                mysql_clear_password: () => () => Buffer.from(this.options.password + '\0')
            }
        });
    }

    async insert (sql, values) {
        const promise = new Promise( (resolve, reject) => {

            try {
                this.pool.query(sql, [values],function (error, results, fields) {
                    if (error) throw error;
                    console.log(results.affectedRows); //Show 1
                    resolve (results.affectedRows);
                });
            } catch (e) {
                reject(e);
            }

        })
        return promise;
    }
}

module.exports = { Connection };

这是我失败的测试:

const conns = require('../src/connection');
const sinon = require('sinon');
const mysql2 = require('mysql2');

describe('handler', () => {

    test('Test insert from Connection', async () => {
        const options = {
            host: 'testHost',
            user: 'testUser',
            password: 'testPassword'
        };

        const poolStub = {
            getConnection: sinon.stub().returnsThis(),
            query: sinon.stub().returnsThis(),
        };

        const createPoolStub = sinon.stub(mysql2, 'createPool').returns(poolStub);
        const conn = new conns.Connection(options);
        await conn.createPool();
        await conn.insert( 'select 1 + 1 as solution', [])

        sinon.restore();
    });
});

测试只是超时。

: Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.

我很确定我在poolStub 中没有正确地存根query,但我不确定如何解释回调方法。我怎样才能对这个insert 方法进行单元测试,以便我可以全面覆盖?

【问题讨论】:

    标签: mysql node.js unit-testing aws-lambda sinon


    【解决方案1】:

    这里是单元测试解决方案:

    connection.js:

    const mysql2 = require('mysql2');
    
    class Connection {
      constructor(options = {}) {
        this.options = options;
      }
    
      createPool() {
        this.pool = mysql2.createPool({
          host: this.options.host,
          user: this.options.user,
          database: 'my_database',
          ssl: 'Amazon RDS',
          password: this.options.password,
          authPlugins: {
            mysql_clear_password: () => () => Buffer.from(this.options.password + '\0'),
          },
        });
      }
    
      async insert(sql, values) {
        const promise = new Promise((resolve, reject) => {
          try {
            this.pool.query(sql, [values], function(error, results, fields) {
              if (error) throw error;
              console.log(results.affectedRows); //Show 1
              resolve(results.affectedRows);
            });
          } catch (e) {
            reject(e);
          }
        });
        return promise;
      }
    }
    
    module.exports = { Connection };
    

    connection.test.js:

    const conns = require('./connection');
    const sinon = require('sinon');
    const mysql2 = require('mysql2');
    const { expect } = require('chai');
    
    describe('handler', () => {
      it('Test insert from Connection', async () => {
        const options = {
          host: 'testHost',
          user: 'testUser',
          password: 'testPassword',
        };
    
        const results = { affectedRows: 1 };
        const poolStub = {
          getConnection: sinon.stub().returnsThis(),
          query: sinon.stub().callsFake((sql, values, callback) => {
            callback(null, results);
          }),
        };
    
        const createPoolStub = sinon.stub(mysql2, 'createPool').returns(poolStub);
        const conn = new conns.Connection(options);
        conn.createPool();
        const actual = await conn.insert('select 1 + 1 as solution', []);
        expect(actual).to.be.eql(1);
        sinon.assert.calledWithExactly(poolStub.query, 'select 1 + 1 as solution', [[]], sinon.match.func);
        sinon.assert.calledWithExactly(createPoolStub, {
          host: 'testHost',
          user: 'testUser',
          password: 'testPassword',
          database: 'my_database',
          ssl: 'Amazon RDS',
          authPlugins: {
            mysql_clear_password: sinon.match.func,
          },
        });
        sinon.restore();
      });
    });
    

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

      handler
    1
        ✓ Test insert from Connection
    
    
      1 passing (15ms)
    
    ---------------|---------|----------|---------|---------|-------------------
    File           | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ---------------|---------|----------|---------|---------|-------------------
    All files      |   73.33 |    33.33 |   71.43 |   84.62 |                   
     connection.js |   73.33 |    33.33 |   71.43 |   84.62 | 16,30             
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-13
      • 2016-12-21
      • 2021-03-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多