I have been successfully able to test a resolved promise on a simple application I have been working on to learn ES6 but been having issues testing the case where there may be network errors.
I wrote this test case:
import {Weather} from '../js/weather';
import chai from 'chai';
import sinon from 'sinon';
import * as chaiAsPromised from 'chai-as-promised';
chai.use(chaiAsPromised);
let assert = chai.assert;
let should = chai.should;
describe('weatherbot-1', function () {
    beforeEach(function () {
        sinon.stub(window, 'fetch');
        let data = '{"cod": "400", "message": "Nothing to geocode"}';
        let res = new window.Response(data, {
            ok: false,
            status: 400,
            headers: {
                'Content-type': 'application/json'
            }
        });
        window.fetch.returns(Promise.reject(res));
    });
    afterEach(function () {
       window.fetch.restore();
    });
    it('should ensure that promise is rejected', function () {
        let weather = new Weather(0, 0);
        return assert.isRejected(weather.getWeather(), 'Rejected');
    });
});
The method in question is:
getWeather() {
        let headers = new Headers();
        let init = {
            method: 'GET',
            headers: headers,
            cache: 'default'
        };
        let url = 'http://localhost:8080/weather?lat=' + '' + '&lon=' + this.longitude;
        return fetch(url, init).then(function (response) {
            return response.json();
        }).catch((error) => {
            return error;
        });
}
For testing the promise, I am using chai-as-promised & chai with mocha & sinon to stub the fetch api.
Whenever I run the test I get this error:
AssertionError: expected promise to be rejected with an error including 'Rejected' but it was fulfilled with { type: 'default',
      url: '',
      redirected: false,
      status: 400,
      ok: false,
      statusText: 'OK',
      headers:
       { append: [Function: append],
         delete: [Function: delete],
         get: [Function: get],
         getAll: [Function: getAll],
         has: [Function: has],
         set: [Function: set],
         keys: [Function: keys],
         values: [Function: values],
         entries: [Function: entries],
         forEach: [Function: forEach] },
      body: {},
      bodyUsed: false,
      clone: [Function: clone],
      arrayBuffer: [Function: arrayBuffer],
      blob: [Function: blob],
      json: [Function: json],
      text: [Function: text] }
From what it looks like, the Promise.reject() may not be working properly. Is there any other way I could test network errors? 
The problem is in getWeather, not the test:
return fetch(url, init)
  .then(function (response) {
    return response.json();
  })
  .catch((error) => {
    return error;
  })
Promise#catch returns a resolved Promise, because its job is to handle errors. The rest of the application should be able to function after catching a rejection, just like with try/catch.
If you want the rejection to reach the test, your code shouldn't catch the rejection:
return fetch(url, init)
  .then(function (response) {
    return response.json();
  })
In general you should only catch where you can properly handle the error. In this example you might want to handle the rejection in a view where you can display an error message.
Also, your code models an invalid situation. fetch returns a resolved Promise for all valid HTTP responses including non-200 status.
It does reject when it cannot make a connection at all, e.g. fetch("http://sdfdsfsd"). In this case it rejects with an Error object.
To properly test a fetch rejection you should simulate this condition and have the stub return Promise.reject(new Error("a message")).
The catch clause in the getWeather function returns a new, fulfilled promise. Basically, catch takes away your ability to test for rejection. What you can do, is use a spy for the rejection handler, and then test it is called.
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