I'm running a test using mocha and sinon to get a callback value from inside a promise scope of HTTP-request and it doesn't work due to the async nature of promises. It's because by the time sinon.spy checks on callback, It would have been vanished already and become empty or undefined. Here's the testing code:
it('should issue GET /messages ', function() {
server.respondWith('GET', `${apiUrl}/messages?counter=0`, JSON.stringify([]));
let callback = sinon.spy();
Babble.getMessages(0, callback);
server.respond();
sinon.assert.calledWith(callback, []);
});
and the promise:
function requestPoll(props) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open(props.method, props.action);
xhr.timeout = 500; // time in milliseconds
if (props.method === 'post' ) {
xhr.setRequestHeader('Content-Type', 'application/json');
}
xhr.addEventListener('load', function(e) {
resolve(e.target.responseText);
});
xhr.send(JSON.stringify(props.data));
});
}
and the call which I'm trying to get callback from on sinon.spy
getMessages: function(counter, callback){
requestPoll({
method: "GET",
action: "http://localhost:9090/messages?counter="+counter
}).then(function(result){
callback(result);
});
}
sinon.spy says it didn't have any arguments (due to async functionality). I tried to look for a way to get result outside the scope and put it on callback.yet I found out it was impossible. also tried resolve and promise return but didn't succeed.
How can I make this unit test pass?
Edit:
this is my attempt:
getMessages: function(counter, callback){
var res;
res = httpRequestAsync("GET",'',"http://localhost:9097/messages?counter=",counter);
console.log(res);
if(res!="")
callback( JSON.parse(res) );
}
I put the request in a separate function:
function httpRequestAsync(method,data,theUrl,counter)
{
return requestPoll({
method: method,
action: theUrl+counter,
data: data
}).then(JSON.parse);
}
It returned res as the promise and inside its prototype there's the promised value I need.
How can I access that promised value over there?
I recommend you not to mix promises and callbacks. If you already have promise based function stick with it
First make getMessages not to break promise chaing. Make it return a Promise
getMessages: function(counter) {
return requestPoll({
method: "GET",
action: "http://localhost:9090/messages?counter=" + counter
}).then(JSON.parse)
}
Then use this promise in your test
it('should issue GET /messages ', function() {
server.respondWith('GET', `${apiUrl}/messages?counter=0`, JSON.stringify([{testdata}]));
const gettingMessages = Babble.getMessages(0);
server.respond();
// return a promise so testing framework knows the test is async
return gettingMessages.then(function(messages) {
// make assertion messages is actually testdata
})
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With