hapijs / lab

Node test utility
Other
739 stars 176 forks source link

Multiple callbacks or errors with Sinon #490

Closed tribou closed 8 years ago

tribou commented 8 years ago

I can't determine if this is an issue with lab, sinon, or my implementation (probably the latter).

I'm receiving the following double callback error even though all tests appear to complete successfully:

WhatLyric API
  ✔ 9) searchByArtistOrTitle calls the server action with the response body data (13 ms)
double callback!

Test script errors:

Multiple callbacks or thrown errors received in test "WhatLyric API searchByArtistOrTitle calls the server action with the response body data" (error): fn is not a function
      at emitOne (events.js:77:13)
      at ClientRequest.emit (events.js:169:7)
      at Socket.socketErrorListener (_http_client.js:259:9)
      at emitOne (events.js:77:13)
      at Socket.emit (events.js:169:7)

There were 1 test script error(s).

9 tests complete
Test duration: 783 ms

I've skipped the test for now, but this is the script:

// Testing the WhatLyric API
import Lab from 'lab';
import Code from 'code';
import Sinon from 'sinon';

// Test shortcuts
const lab = exports.lab = Lab.script();
const describe = lab.describe;
const it = lab.it;
const expect = Code.expect;
const after = lab.after;
const before = lab.before;

describe('WhatLyric API', () => {
  let Request;
  let ServerActions;
  let searchByArtistOrTitle;
  let stubRequest;
  let stubServerActions;

  const response = {
    body: {
      data: 'test',
    },
  };

  before(done => {
    // stub the superagent response
    Request = require('superagent');
    stubRequest = Sinon.stub(Request.Request.prototype, 'end', callback => {
      return callback(null, response);
    });
    // stub the server action method
    ServerActions = require('../actions/SearchServerActions.js');
    stubServerActions = Sinon.stub(ServerActions, 'receiveSearchByArtistOrTitle');
    searchByArtistOrTitle = require('./WhatLyricAPI.js').searchByArtistOrTitle;
    done();
  });

  it('searchByArtistOrTitle calls the server action with the response body data', { skip: true }, done => {
    searchByArtistOrTitle();
    expect(stubServerActions.getCall(0).args[0]).to.equal(response.body.data);
    done();
  });

  after(done => {
    // restore all sinon objects
    Request.Request.prototype.end.restore();
    ServerActions.receiveSearchByArtistOrTitle.restore();
    done();
  });
});

Here's the line that's causing the issue in the context of the project: https://github.com/tribou/whatlyric/blob/master/web/react/utils/WhatLyricAPI_test.js#L41

When inspecting the sinon firstCall.stack error for the stub, it has this:

Error
    at Function.invoke (/Users/dev/whatlyric/node_modules/sinon/lib/sinon/spy.js:187:40)
    at proxy (eval at createProxy (/Users/dev/whatlyric/node_modules/sinon/lib/sinon/spy.js:77:86), <anonymous>:1:35)
    at /Users/dev/whatlyric/web/react/utils/WhatLyricAPI.js:23:160
    at Request.<anonymous> (/Users/dev/whatlyric/web/react/utils/WhatLyricAPI_test.js:47:111)
    at Function.invoke (/Users/dev/whatlyric/node_modules/sinon/lib/sinon/spy.js:172:59)
    at Request.proxy [as end] (eval at createProxy (/Users/dev/whatlyric/node_modules/sinon/lib/sinon/spy.js:77:86), <anonymous>:1:35)
    at searchByArtistOrTitle (/Users/dev/whatlyric/web/react/utils/WhatLyricAPI.js:20:179)
    at /Users/dev/whatlyric/web/react/utils/WhatLyricAPI_test.js:57:102
    at Immediate._onImmediate (/Users/dev/whatlyric/node_modules/lab/lib/runner.js:467:17)
    at processImmediate [as _immediateCallback] (timers.js:383:17)

The only similar issue I could find that involved the runner and timers was Feature - Prevent clobbered timer globals from interfering with runner.

If there's a better implementation for this test, I'm definitely open to suggestions.

Marsup commented 8 years ago

Not sure if it's the cause but maybe you should wait for the callback to return before marking the test as done, you might be undoing the stub a bit too early.

geek commented 8 years ago

This is an issue with not handling the error event: https://github.com/nodejs/node/blob/master/lib/_http_client.js#L259

I am guessing its an issue in superagent or how its being used with sinon.

tribou commented 8 years ago

@geek, you were correct. This was an issue with the superagent package which was fixed by visionmedia/superagent@454eeb2.

The updated test at tribou/whatlyric@4a167111d781c5180633ebde6ac5e942fe5a6f49 no longer throws an error.

lock[bot] commented 4 years ago

This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.