Edo
Edo

Reputation: 1589

How to test events generated from node.js http request?

I have a node.js code that I'm testing with mocha and sinon

var request = require('request');
request.get(url, function (error, response, body) {
  /* code I already tested */
})
.on('error', function(err) {
  /* code I want to test */
})

I have created a stub with sinon var requestGet = sinon.stub(request, 'get'); and I created different units to test the /* code I already tested */

Now I want to test the code /* code I want to test */ executed when request.get() emit an error event but I don't know how to do it.

Upvotes: 0

Views: 1379

Answers (1)

Antonio Narkevich
Antonio Narkevich

Reputation: 4326

You just need to make your own EventEmitter, stub the .get method and use it however you want. You'll be able to emit any events:

//Stubbing
emitter = new EventEmitter();
sandbox.stub(request, 'get').returns(emitter);

//And when you need to fire the event:
emitter.emit('error', new Error('critical error'));

Here is an example.

Say you have a method makeRequest. And you want to test that in case of critical error the application must be stopped by calling application.stop().

Here is how you could test it (please see my comments):

const request = require('request');
const sinon = require('sinon');
const assert = require('assert');
const { EventEmitter } = require('events');

const application = { stop () { console.log('appliation is stopped') } };

const makeRequest = () => {
    return request
        .get('http://google.com', function (error, response, body) {
            if (error) { return console.error(error); }

            console.log('executed');
        })
        .on('error', err => {
            if (err.message === 'critical error') {
                application.stop();
            }
        });
}

describe('makeRequest', () => {
    let emitter;

    let sandbox = sinon.createSandbox();
    let stopSpy;

    beforeEach(() => {
        // Using our own emitter. We'll be able to raise any events.
        emitter = new EventEmitter();

        // We don't want the standard `get` logic to be executed as we are testing the error only.
        // Notice - we are returning `emitter` so the .on method exists.
        sandbox.stub(request, 'get').returns(emitter);

        stopSpy = sandbox.spy(application, 'stop');
    });


    it('should stop the app in case of a critical error', () => {
        // No need to worry about the callbacks, the stubbed method is sync.
        makeRequest();

        // Now emitting the error.
        emitter.emit('error', new Error('critical error'));

        // Checking if the required method has been called.
        assert.equal(stopSpy.calledOnce, true);
    });

    afterEach(() => sandbox.restore());
})

Upvotes: 3

Related Questions