timmy
timmy

Reputation: 1758

Jasmine Test Consecutive Promise Calls

I have the following test that does the following:

  1. Makes a mocked out service call that returns a promise which resolves to some currency codes.
  2. Assert that the currency codes that are set on the controller's scope match what was returned by the mocked out service.
  3. Makes a second mocked out service call that results in an error.
  4. Assert that the currency codes set on the controller's scope are null.

The assertion at step 2 fails because the currency codes are null. It seems like I can't sequence the promises in my test. The code is below:

    beforeEach(inject(function($rootScope, $controller, $log, $q) {
        //.....
        spyOn(clientMoneyService, findCurrencyCodes').andReturn(deferral.promise);
}));

it('should clear currency codes on error', inject(function() {
    scope.findCurrencyCodes();
    // first call returns currencies
    deferral.resolve(response);
    var response = {
        data: ['AUD', 'CAD']
    };
    scope.$apply();
    expect(scope.currencyCodes).toEqual(['AUD', 'CAD']);

    // second call errors out
    deferral.reject();
    scope.findCurrencyCodes();
    scope.$apply();
    expect(scope.currencyCodes).toBeNull();
}));

Is there a way to sequence my promises so that on the first call I get a list of currency codes and the second call I get an error?

Upvotes: 0

Views: 473

Answers (1)

scarlz
scarlz

Reputation: 2512

Any given promise can only be used to return one outcome (be it resolved or rejected), so trying to reject a promise subsequent to resolving it will not work. The simplest way to test your method would be to split your test into two, with one for each outcome:

it('should resolve to currency codes on success', function() {
  scope.findCurrencyCodes();      
  deferral.resolve({data: ['AUD', 'CAD']});
  scope.$digest();
  expect(scope.currencyCodes).toEqual(['AUD', 'CAD']);
});

it('should clear currency codes on error', function() {     
  scope.currencyCodes = ['AUD', 'CAD'];
  scope.findCurrencyCodes();
  deferral.reject();
  scope.$digest();
  expect(scope.currencyCodes).toBeNull();
});

If for some reason you really have to assert both within the same test, you would need to amend your stub for findCurrencyCodes to return a new promise each time it's called.

Upvotes: 1

Related Questions