Nate
Nate

Reputation: 1750

Unit testing NodeJS Promise inside a function

Im trying to unit test a function that calls a promise...

Using Mocha, Sinon. I have a functional block like this:

myfile.js:

    let OuterDependecy = require('mydep');
    function TestFunction(callback) {
        OuterDependency.PromiseFunction().then(response => {  

       //some logic here
     }).catch(err => {callback(err)});

inside my test i have used proxyquire to mock the outerdependecy

testfile.js

let proxyquire = require('proxyquire');
let OuterDepStub = {};
let testingFunc = proxyquire('myfile.js', {'mydep': OuterDepStub});

... then inside my testing block

    let stubCallback = function() {
                console.log('Stub dubadub dub'); //note...i can use sinon.spy here instead
    };

   beforeEach(()=>{
            OuterDependency.PromiseFunction = function(arg) {
               return  new Promise((resolve, reject)=>{
                   reject('BAD');
               });
            };


            spy = sinon.spy(stubCallback);
       });

my actual test now calls the main "testfunction"

it('Catches Errors, and calls back using error', done => {
            TestFunction(stubCallback);
            expect(spy).to.have.been.called;
            done();
        });

I see the stub being called (the console log, hence why i didnt want to use sinon.spy) but the spy is saying its not called. and unit test fails.

I believe this is probably due to a race condition of sorts where the promise is resolving after my test is run... is there anyway to delay the test until my promise is resolve.

i know in in angularjs promise testing, there was a way to "tick" the promise so it resolves when you want to. possible in nodejs?

Upvotes: 1

Views: 1532

Answers (1)

Sergeon
Sergeon

Reputation: 6788

  • is there anyway to delay the test until my promise is resolve.

As far as I understand your issue, yes, you should only call done() after the promise is settled. In order to do that,you need two things:

1- Enforce TestFunction to return a Promise, so you can wait until it resolves:

    function TestFunction(callback) {
     return OuterDependency.PromiseFunction().then(response => {

        //some logic here
    }).catch(err => { callback(err) });
}

2- Wait to that promise to settle, then call done.

it('Catches Errors, and calls back using error', done => {
    TestFunction(stubCallback).then(() => {
        expect(spy).to.have.been.called;
        done();
    })
});

now, our then block won't run until the catch block within TestFunction, so if the test works as expected (i.e. the catch block fires and the callback gets fired), the expectation and the done calls will always fire after the callback gets called.

  • I see the stub being called (the console log, hence why i didnt want to use sinon.spy) but the spy is saying its not called. and unit test fails.

That's because your expectation runs right after the TestFunction calls, without waiting for it to settle. However, it will get called lately, thus the console.log appears in the next spec.

Upvotes: 1

Related Questions