2017-07-08 115 views
2

我已经成功地在一个简单的应用程序上测试了一个已解决的承诺,我一直在努力学习ES6,但一直在测试可能存在网络错误的情况。如何测试抓取api中的网络错误?

我写这个测试用例:

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'); 
    }); 
}); 

问题的方法是:

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; 
     }); 
} 

为了测试的承诺,我使用chai-as-promised & chaimocha & sinon存根的fetch API 。

每当我运行测试我得到这个错误:

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] } 

从什么样子,在Promise.reject()可能无法正常工作。有没有其他方法可以测试网络错误?

回答

3

的问题是getWeather,不是测试:

return fetch(url, init) 
    .then(function (response) { 
    return response.json(); 
    }) 
    .catch((error) => { 
    return error; 
    }) 

Promise#catch返回解决承诺,因为它的工作是处理错误。应用程序的其余部分应该能够在捕获拒绝之后起作用,就像try/catch一样。

如果你想甩去达到测试,你的代码应该能赶上拒绝:

return fetch(url, init) 
    .then(function (response) { 
    return response.json(); 
    }) 

一般来说,你应该只catch在那里你可以妥善处理错误。在这个例子中,您可能想要在视图中处理拒绝,您可以显示错误消息。

此外,您的代码模型无效的情况。 fetch返回一个解决承诺所有有效的HTTP响应,包括非200状态。

当它完全无法建立连接时,它会拒绝。 fetch("http://sdfdsfsd")。在这种情况下,它会拒绝Error对象。

要正确测试fetch拒绝,您应模拟此条件并将存根返回Promise.reject(new Error("a message"))

+0

感谢您的回答,我删除了'catch',但我得到一个新的错误:在Object.compatibleMessage(测试/ rejectedPromise.js无法读取属性未定义 \t“的indexOf”: '类型错误825 :254) \t at test/rejectedPromise.js:8036:1432 \t at ' – thedeliciousmuffin

+0

这听起来像是'assert.isRejected'中的一个错误。我期望它假定拒绝值是一个带有'message'属性的'Error'。如果您向拒绝中添加“讯息”,错误是否会消失?我知道这不会是一个代表'fetch'拒绝,但它会帮助诊断问题。 – joews

+0

事实上,读取你的代码更多 - Promise不会拒绝'fetch'。 'fetch'返回一个已解析的Promise,用于非200错误代码的有效HTTP响应。 – joews

1

getWeather函数中的catch子句返回一个新的已履行承诺。基本上,捕捉带走了测试拒绝的能力。你可以做什么,就是使用一个间谍为拒绝处理程序,然后测试它被调用。