Reputation: 511
I have a Node.js function that returns a promise. I am using Sinon.JS stubs to resolve the promise. My console.log statements in the code show that the stub is working. However, what is returned is {}
instead of what the Promise resolves to.
I reviewed these other SO posts, but neither were exactly the problem I am running into:
Here is the function:
function publishMessage(pubsub, topicName, data) {
const topic = pubsub.topic(topicName);
const publisher = topic.publisher();
return publisher.publish(data)
.then((results) => {
const messageId = results[0];
return messageId;
})
.catch((error) => {
console.log('Error ', error);
return error;
}); };
Here is the test:
describe('publishMessage', function() {
describe('Success', function() {
it('should return the messageId', function(done) {
var publishMessage = index.__get__('publishMessage');
var promise = sinon.stub().resolves(['1111']);
var publisher = {
publish: promise
};
var topic = {
publisher: sinon.stub().returns(publisher)
};
var pubsub = {
topic: sinon.stub().returns(topic)
};
assert.equal('1111', publishMessage(pubsub, 'st', 'ds'));
assert.isTrue(topic.publisher.calledWith());
done();
});
});
});
And when I execute the test, the output from the console.log
shows the resolve value is printed:
publishMessage
Success
1) should return the messageId
1111
0 passing (256ms)
1 failing
1) publishMessage
Success
should return the messageId:
AssertionError: expected '1111' to equal {}
at Context.<anonymous> (test/index.spec.js:63:14)
Upvotes: 1
Views: 5092
Reputation: 1867
There's a few potential problem areas that I noticed.
First, I don't see where index
is defined, so I can't confirm whether or not the function you expect is being returned from index.__get__('publishMessage');
. You can confirm that the right function is returned by visually inspecting the result of
publishMessage.toString();
The other problem I see (and more likely the cause of your problem) is that you are returning a Promise from publishMessage()
, but comparing the result of a call to that function to the value to which the Promise will eventually resolve. In other words, your comparing a Promise to a String. Unless your assertion library waits for the Promise to resolve before checking the result (similar to Jasmine), you are comparing a String to a Promise. To remedy this, simply wait for the Promise to resolve:
it('should return the messageId', function(done) {
// Set up the test case by defining publishMessage, etc.
publishMessage(pubsub, 'st', 'ds').then((result) => {
assert.equal(result, '1111');
assert.isTrue(topic.publisher.calledWith());
done();
}).catch(done);
}
Notice I added a .catch()
on the Promise. This makes sure that any errors thrown in the Promise will show the appropriate error as opposed to just a timed out error.
If you're using a testing framework like Mocha or Karma/Jasmine, you can improve this a little more by directly returning the Promise instead of using done()
. In my experience, returning the Promise results in much better stack traces and more helpful and accurate error messages when trying to debug a test case that uses Promises. As an example:
it('should return the messageId', function() {
// Set up the test case by defining publishMessage, etc.
return publishMessage(pubsub, 'st', 'ds').then((result) => {
assert.equal(result, '1111');
assert.isTrue(topic.publisher.calledWith());
});
}
Notice that I don't accept an argument in the test case anymore. In Mocha and Karma, this is how the framework determines how to treat the test case.
Upvotes: 3
Reputation: 3340
You don't wait for your promise to be resolved.
Try
publishMessage(pubsub, 'st', 'ds').then(result => {
assert.equal('1111', result);
assert.isTrue(topic.publisher.calledWith());
done();
}
Upvotes: 2