mocking/stubing/unit testing mysql streaming查询行node js

nnvyjq4y  于 2021-06-23  发布在  Mysql
关注(0)|答案(2)|浏览(292)

我有一个下面的函数,它使用mysql node js模块的流式查询行。如何对下面的函数进行单元测试,我还想模拟数据库行为,而不是在单元测试时连接到数据库processrow和wirtecsvfile函数都是同步任务。

function executeTask(sql_connection,sql_query) {

 let query = sql_connection.query(sql_query);
 let showInfo = {};
 let showids = [];
 query
 .on('error', (error) => {
   console.error(`error executing query --> ${error}`);
 })
 .on('result', function (row) {
   sql_connection.pause();
   processRow(row, showInfo, showids, function () {
     sql_connection.resume();
   });
 })
 .on('end', function () {
  showids.forEach(showid => {
    if (showInfo[showid].faults.length === 0) {
      delete showInfo[showid];
    }
  });
  wirteCsvFile(showInfo, (error, done) => {
    if (error) {
      console.error(error);
    } else {
      console.log("done");
      process.exit();
    }
  })
 });
}
flmtquvp

flmtquvp1#

我想我们可以嘲笑 sql_connection 一类事件发射器。

const sinon = require("sinon");
const assert = require('assert');
const EventEmitter = require('events');
const src = require('....'); // your source file that contain `executeTask`

// Create mock emitter
class QueryEmitter extends EventEmitter {}

describe('test execute task', function() {      
  const queryEmitter = new QueryEmitter();

  // we build mock connection that contains all methods used as in `sql_connection`
  const conn = { 
    query: sinon.stub().returns(queryEmitter),
    pause: sinon.spy(),
    resume: sinon.spy() 
  };

  const query = 'SELECT *';

  before(function() {
    src.executeTask(conn, query);
  });

  it('calls query', function() {
    assert(conn.query.calledWith(query));
  });

  it('on result', function() {    
    queryEmitter.emit('result');    
    assert(conn.pause.called);
    // assert if processRow is called with correct arguments
    // assert if conn.resume is called
  });

  it('on end', function() {    
    queryEmitter.emit('end');    
    // assert if writeCsvFile is called
  });

  // probably is not needed since you only call console.log here     
  it('on error', function() {        
    queryEmitter.emit('error');
  });  
});

希望有帮助

mwecs4sa

mwecs4sa2#

你可以用树桩 query 函数返回所需的内容,而不是向数据库发出请求: sinon.stub(connection, "query").callsFake(() => /* whatever you want here */); 你也应该休息一下 executeTask 变成更小的函数,例如:

function errorHandler(error) {
    console.error(`error executing query --> ${error}`);
}

function resultHandler(data, row) {
    sql_connection.pause();
    processRow(row, data.showInfo, data.showids, function() {
        sql_connection.resume();
    });
}

function endHandler(data) {
    data.showids.forEach(showid => {
        if (data.showInfo[showid].faults.length === 0) {
            delete data.showInfo[showid];
        }
    });

    wirteCsvFile(data.showInfo, (error, done) => {
        if (error) {
            console.error(error);
        } else {
            console.log("done");
            process.exit();
        }
    })
}

function executeTask(sql_connection, sql_query) {
    let query = sql_connection.query(sql_query);
    let data = {
        showInfo: {},
        showids: [],
    };

    query.on('error', errorHandler)
    .on('result', resultHandler.bind(null, data))
    .on('end', endHandler.bind(null, data));
}

现在你可以测试了 errorHandler , resultHandler , endHandler 分别地

相关问题