Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test a stub returning a promise in an async test?

How can I test this in a async manner?

it('Should test something.', function (done) {

    var req = someRequest,
        mock = sinon.mock(response),
        stub = sinon.stub(someObject, 'method');

     // returns a promise
     stub.withArgs('foo').returns(Q.resolve(5));

     mock.expects('bar').once().withArgs(200);

     request(req, response);

     mock.verify();

});

And here is the method to test.

var request = function (req, response) {

    ...

    someObject.method(someParameter)
        .then(function () {
            res.send(200);
        })
        .fail(function () {
            res.send(500);
        });

};

As you can see I am using node.js, Q (for the promise), sinon for mocking and stubbing and mocha as the test environment. The test above fails because of the async behaviour from the request method and I don't know when to call done() in the test.

like image 535
Stefan Avatar asked Apr 15 '13 12:04

Stefan


People also ask

Do async functions return a promise?

Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.

Can we use async with promises?

async and awaitInside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.

How do you mock promise?

In order to mock asynchronous code in Jest, more specifically Promises, you can use the mockResolvedValue function. This will mock the return value of the Promise to be 42. In order to test a Promise in Jest, you need to turn your it block into async in order to use the await keyword in front of an expect statement.

Are promises executed asynchronously?

A promise is used to handle the asynchronous result of an operation. JavaScript is designed to not wait for an asynchronous block of code to completely execute before other synchronous parts of the code can run. With Promises, we can defer the execution of a code block until an async request is completed.


2 Answers

You need to call done once all the async operations have finished. When do you think that would be? How would you normally wait until a request is finished?

it('Should test something.', function (done) {

   var req = someRequest,
       mock = sinon.mock(response),
       stub = sinon.stub(someObject, 'method');

    // returns a promise
    stub.withArgs('foo').returns(Q.resolve(5));

    mock.expects('bar').once().withArgs(200);

    request(req, response).then(function(){
       mock.verify();
       done();
    });

});

It might also be a good idea to mark your test as failing in an errorcallback attached to the request promise.

like image 173
Frances McMullin Avatar answered Oct 20 '22 10:10

Frances McMullin


Working solution in Typescript:

 var returnPromise = myService.method()
    returnPromise.done(() => {
        mock.verify()
    })
like image 22
Łukasz Rzeszotarski Avatar answered Oct 20 '22 11:10

Łukasz Rzeszotarski