How does one stub promise with sinon?

JavascriptJasmineSinon

Javascript Problem Overview


I have a data service with following function

function getInsureds(searchCriteria) {
               
	var deferred = $q.defer();
	
	insuredsSearch.get(searchCriteria,
		function (insureds) {
			deferred.resolve(insureds);
		},
		function (response) {
			deferred.reject(response);
		});

	return deferred.promise;
}
  

I want to test following function:

function search ()
{
  dataService
      .getInsureds(vm.searchCriteria)
      .then(function (response) {
           vm.searchCompleted = true;
                
            if (response.insureds.length > 100) {
              vm.searchResults = response.insureds.slice(0, 99);
            } else {
                vm.searchResults = response.insureds;
           }
       });
}

How would I stub the promise so that when I call getInsureds it would resolve the promise and return me the results immediately. I started like this (jasmine test), but I am stuck, as I don't know how to resolve the promise and pass in arguments needed.

it("search returns over 100 results searchResults should contain only 100 records ", function () {

	var results103 = new Array();

	for (var i = 0; i < 103; i++) {
		results103.push(i);
	}

	var fakeSearchForm = { $valid: true };
	var isSearchValidStub = sinon.stub(sut, "isSearchCriteriaValid").returns(true);

	var deferred = $q.defer();
	var promise = deferred.promise;
	var dsStub = sinon.stub(inSearchDataSvc, "getInsureds").returns(promise);

	var resolveStub = sinon.stub(deferred, "resolve");
	
	//how do i call resolve  and pass in results103

	sut.performSearch(fakeSearchForm);
	
	sinon.assert.calledOnce(isSearchValidStub);
	sinon.assert.calledOnce(dsStub);

	sinon.assert.called(resolveStub);
	
	expect(sut.searchResults.length).toBe(100);

});

Javascript Solutions


Solution 1 - Javascript

At current sinon version v2.3.1, you can use stub.resolves(value) and stub.rejects(value) function

For example, you can stub myClass.myFunction with following code

sinon.stub(myClass, 'myFunction').resolves('the value you want to return');

or

sinon.stub(myClass, 'myFunction').rejects('the error information you want to return');

Solution 2 - Javascript

You just have to resolve the promise before you call the search function. This way your stub will return a resolved promise and then will be called immediately. So instead of

var resolveStub = sinon.stub(deferred, "resolve");

you will resolve the deferred with your fake response data

deferred.resolve({insureds: results103})

Solution 3 - Javascript

Also you can do something like this:

import sinon from 'sinon';

const sandbox = sinon.sandbox.create();

const promiseResolved = () => sandbox.stub().returns(Promise.resolve('resolved'));
const promiseRejected = () => sandbox.stub().returns(Promise.reject('rejected'));

const x = (promise) => {
  return promise()
    .then((result) => console.log('result', result))
    .catch((error) => console.log('error', error))
}

x(promiseResolved); // resolved
x(promiseRejected); // rejected

Solution 4 - Javascript

I had a similar situation and the accepted answer and comments were not working, but along with this question they helped me solve this in the following way. I hope it is helpful for somebody.

var Promise = require('bluebird');

var deferred = Promise.defer();
stub = sinon.stub(deferred, 'resolve').returns(deferred.promise);

deferred.resolve({data: data});
// or
deferred.reject(new Error('fake error'));

Solution 5 - Javascript

There's one more alternative I found. Much pain free than other methods.

You can use this npm package: sinon-stub-promise.

It abstracts much of the details, so that you don't have to invent the wheel again. Helped my write my tests after struggling to simulate a promise for long.

Hope it helps!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionepitkaView Question on Stackoverflow
Solution 1 - JavascriptYu HuangView Answer on Stackoverflow
Solution 2 - JavascriptAndreas KöberleView Answer on Stackoverflow
Solution 3 - JavascriptaH6yView Answer on Stackoverflow
Solution 4 - JavascriptWtowerView Answer on Stackoverflow
Solution 5 - JavascripttbkingView Answer on Stackoverflow