0

I ran into an issue today where I had passing tests that should have failed. There were some incorrectly stubbed methods using Sinon that failed to stub out the callback correctly. I would have expected execution to fail, but it passed the test, however it stopped execution early because my test messages quit logging to the console at the incorrectly stubbed method invocation.

The code I had was similar to the following:

exports.myFunc = function (req, res) {
  var innerFunc = function(callback) {
    fs.exists('some/dir', function (exists) {
      if (!exists) { // handle error }
      else {
        logger.log('this prints to the console');
        utilModule.stubbedMethod('some/dir', callback); 
      }
    });
  };

  logger.log('this also prints to the console');
  innerFunc(function (err, value) {
    logger.log('this does not print to the console');
    if (err) {
      logger.log('this does not print to the console');
      res.status(500).send(err);
    } else {
      logger.log('this does not print to the console, either');
      res.send('success');
    }
  });
});

// This is the tests, now:

var app = require('../app'),
    mod = require('../lib/myModule'),
    request = require('supertest'),
    chai = require('chai'),
    sinon = require('sinon');

describe('For module myModule', function () {
  ...
  describe('#myFunc', function () {
    var fs = require('fs'),
        util = require('../lib/utilModule');

  describe('Happy path', function () {
    var expectedResult = "expected";

    before(function() {
      sinon.stub(fs, 'exists').yields(true, null);
      sinon.stub(mod, 'stubbedMethod').yield("some value");
      // the above is wrong and should have been yield(null, null, "some value")
    });

    after(function () { fs.exists.restore(); mod.stubbedMethod.restore(); });

    it('Replies with the right value and status 200', function () {
      request(app).get('/url').expect(200, 'success').end(function(err, res) {
        if (err) throw err;
      }
    });
  });
});

Why did this test pass, and is there some way to prevent it from passing?

josiah
  • 1,314
  • 1
  • 13
  • 33
  • After thinking about it, I'm pretty sure this is because the actual assertion must happen within the callback of my API endpoint. Thus, if that callback never gets called because the method calling the callback is incorrectly stubbed, the assertion is never encountered, so then Mocha assumes this is an unimplemented unit test and passes it, silently ignoring the error. – josiah Feb 27 '15 at 15:28
  • It's also occurred to me that `yield` is specifically used for functions that take a callback as a parameter. Why didn't Sinon detect in the before block that this method couldn't possibly be stubbed correctly? – josiah Feb 27 '15 at 17:58

0 Answers0