javascript - Sinon.stub() return different values every time it's called -


here code writing tests for:

'use strict';  var internals = {};  var _ = require('lodash');  module.exports = {     initialize: function (query) {         internals.query = query;     },      createfield: function (fieldid, accountid, payload) {          function callquery (parlist) {             var query = 'insert fields values (:uuid, :accountid, :shortcutname, :displayname, :fieldtype, :widgettype, :columnorder, :options, :required, null)';             return internals.query(query, parlist, function () { return fieldid; });         }          var increment = 10;         var parameterlist = {             'uuid': fieldid,             'accountid': accountid,             'shortcutname': payload.shortcutname,             'displayname': payload.displayname,             'fieldtype': payload.fieldtype,             'widgettype': payload.widgettype,             'columnorder': payload.columnorder,             'options': json.stringify(payload.options) || null,             'required': payload.required || 'f'         };         if (!payload.columnorder) {             var columnquery = 'select max(column_order) fields';             return internals.query(columnquery, {}, function (x) {return x; })                 .then(function (results) {                     var highestcolumnorder = results[0]['max(column_order)'];                     var newhighestcolumnorder = math.ceil(highestcolumnorder / 10) * 10;                     if (newhighestcolumnorder > highestcolumnorder) {                         parameterlist.columnorder = newhighestcolumnorder;                     } else {                         parameterlist.columnorder = newhighestcolumnorder + increment;                     }                     return callquery(parameterlist);                 });         } else {             return callquery(parameterlist);         }     },      getfieldsbyaccountid: function(accountid, showdeleted) {         var callquery = function(paramlist) {             var query = 'select ' + paramlist.columns.join(", ") + ' fields account_id = :account_id';              if (!showdeleted) {                 query +=  ' , archived_at null';             }              return internals.query(query, paramlist, function(rows) {                 return _.each(rows, function(row) {                     if(row.options) {                         row.options = json.parse(row.options);                     }                     row.required = !!row.required;                 });             });         };          var columnlist = ["uuid", "account_id", "shortcut_name", "display_name", "field_type", "required", "column_order", "options"];         var paramlist = {'account_id': accountid};          if (showdeleted) {             columnlist.push("archived_at");         }          _.extend(paramlist, {'columns': columnlist});          return callquery(paramlist);     } }; 

here test:

        'use strict';  var assert = require('assert'); var sinon = require('sinon'); var promise = require('bluebird'); var proxyquire = require('proxyquire');  var returnedvalues = require('../../../return_values.js'); var fieldgateway = proxyquire('../../../../src/fields/lib/gateway', {});  describe('gateway', function () {     var accountid = 100;     var fieldid = 200;     var _query, sql, mockdata, rows;      describe('createfield', function() {         describe('is successful column order value', function () {              beforeeach(function() {                 sql = 'insert fields values (:uuid, :accountid, :shortcutname, :displayname, :fieldtype, :widgettype, :columnorder, :options, :required, null)';                 mockdata = returnedvalues.getfieldinputvalues();             });              it("should insert new field", function () {                 _query = sinon.spy(function() { return promise.resolve(); });                 fieldgateway.initialize(_query);                 fieldgateway.createfield(fieldid, accountid, mockdata);                  mockdata.accountid = accountid;                 mockdata.uuid = fieldid;                 mockdata.options = json.stringify(mockdata.options);                 assert.equal(sql, _query.getcall(0).args[0]);                 assert.deepequal(mockdata, _query.getcall(0).args[1]);             });              it.only("_query should called right sql statement , parameterlist", function () {                 _query = sinon.stub().returns(promise.resolve(fieldid));                 // _query.oncall(0).returns(promise.resolve([{'max(column_order)': 10}]));                 // _query.oncall(1).returns(promise.resolve(fieldid));                 fieldgateway.initialize(_query);                 delete mockdata.columnorder;                  fieldgateway.createfield(fieldid, accountid, mockdata);                 console.log(_query.args);                 assert.equal(sql, _query.getcall(0).args[0]);                  fieldgateway.createfield.restore();             });         });     });  }); 

the problem when test runs, sql query runs select statement. should happen 1 sql statement runs, insert statement runs

this happens because bluebird true promise/a+ compliant library. , definition chained promises must run in different execution tick. first promise executed synchronously (in same tick).

you should tell mocha "wait" rest act. specifying done callback in unit test , calling accordingly when promises finished job

 it.only("_query should called right sql statement , parameterlist", function (done) {     _query = sinon.stub().returns(promise.resolve(fieldid));     fieldgateway.initialize(_query);     delete mockdata.columnorder;     fieldgateway.createfield(fieldid, accountid, mockdata)     .then(function(){            /// assertion code should adjusted here          console.log(_query.args);          assert.equal(sql, _query.getcall(0).args[0]);          fieldgateway.createfield.restore();          //tell mocha we're done, can stop waiting          done();     })     .catch(function(error) {        //in case promise chain rejected unexpectedly       //gracefully fail test          done(error);      }; }); 

whenever test promise-returning functions should handle result in .then


Comments