2017-07-08 60 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子句返回一個新的已履行承諾。基本上,捕捉帶走了測試拒絕的能力。你可以做什麼,就是使用一個間諜爲拒絕處理程序,然後測試它被調用。