我已成功地在一个简单的应用程序上测试已解决的承诺,我一直在努力学习ES6,但在测试可能存在网络错误的情况时遇到了问题。
我写了这个测试用例:
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
& chai
与mocha
& 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()
可能无法正常工作。有没有其他方法可以测试网络错误?
答案 0 :(得分:3)
问题出在 $(document).ready(function() {
$('#prof-rendi').click(function() {
$('.graph-loading').show();
$('#svg-quarter').empty();
var tooltip = tooltipd3();
var svg = d3.select("svg#svg-quarter"),
margin = {
top: 20,
right: 20,
bottom: 30,
left: 40
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
y = d3.scaleLinear().rangeRound([height, 0]);
var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var div = d3.select("#svg-quarter").append("div"). // declare the tooltip div
attr("class", "tooltip"). // apply the 'tooltip' class
style("opacity", 0);
d3.csv(base_url() + 'graph/getStatementsQuarterly/', function(d) {
$('.graph-loading').hide();
d.guadagno = +d.guadagno;
return d;
}, function(error, data) {
if (error)
throw error;
x.domain(data.map(function(d) {
return d.periodo;
}));
y.domain([
0,
d3.max(data, function(d) {
return d.guadagno;
})
]);
g.append("g").attr("class", "axis axis--x").attr("transform", "translate(0," + height + ")").call(d3.axisBottom(x));
g.append("g").attr("class", "axis axis--y").call(d3.axisLeft(y).ticks(10)).append("text").attr("transform", "rotate(-90)").attr("y", 6).attr("dy", "0.71em").attr("text-anchor", "end").text("Guadagno")
g.selectAll(".bar").data(data).enter().append("rect").attr("class", "bar").attr("x", function(d) {
return x(d.periodo);
}).attr("y", function(d) {
return y(d.guadagno);
}).attr("width", x.bandwidth()).attr("height", function(d) {
return height - y(d.guadagno);
}).on('mouseover', function(d) {
var html = '<h5>' + d.guadagno + ' €</h5>';
tooltip.mouseover(html); // pass html content
}).on('mousemove', tooltip.mousemove).on('mouseout', tooltip.mouseout);
});
});
$('.quarter-increase, .quarter-decrease').on('click', function() {
$('.rendi-btn.left, .rendi-btn.right').attr('disabled', 'disabled');
var where_at = $('#scroll-statement-quarter').val();
$('.graph-loading').show();
$('#svg-quarter').css({'opacity': 0.4});
var tooltip = tooltipd3();
var svg = d3.select("svg#svg-quarter"),
margin = {
top: 20,
right: 20,
bottom: 30,
left: 40
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
y = d3.scaleLinear().rangeRound([height, 0]);
var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var div = d3.select("#svg-quarter").append("div"). // declare the tooltip div
attr("class", "tooltip"). // apply the 'tooltip' class
style("opacity", 0);
var speed = 500;
d3.csv(base_url() + 'graph/getStatementsQuarterly/' + where_at, function(d) {
$('.graph-loading').hide();
d.guadagno = +d.guadagno;
return d;
}, function(error, data) {
if (error)
throw error;
x.domain(data.map(function(d) {
return d.periodo;
}));
y.domain([
0,
d3.max(data, function(d) {
return d.guadagno;
})
]);
g.append("g").attr("class", "axis axis--x").attr("transform", "translate(0," + height + ")").call(d3.axisBottom(x));
g.append("g").attr("class", "axis axis--y").call(d3.axisLeft(y).ticks(10)).append("text").attr("transform", "rotate(-90)").attr("y", 6).attr("dy", "0.71em").attr("text-anchor", "end").text("Guadagno")
g.selectAll(".bar").data(data).transition().duration(speed).attr("class", "bar").attr("x", function(d) {
return x(d.periodo);
}).attr("y", function(d) {
return y(d.guadagno);
}).attr("width", x.bandwidth()).attr("height", function(d) {
return height - y(d.guadagno);
}).on('mouseover', function(d) {
var html = '<h5>' + d.guadagno + ' €</h5>';
tooltip.mouseover(html); // pass html content
}).on('mousemove', tooltip.mousemove).on('mouseout', tooltip.mouseout);
});
})
});
,而不是测试:
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
为所有有效的HTTP响应(包括非200状态)返回已解决的承诺。
当它根本无法建立连接时会拒绝,例如fetch
。在这种情况下,它拒绝使用fetch("http://sdfdsfsd")
对象。
要正确测试Error
拒绝,您应该模拟此条件并让存根返回fetch
。
答案 1 :(得分:1)
getWeather
函数中的catch子句返回一个新的,履行的承诺。基本上,catch会剥夺你测试拒绝的能力。你可以做什么,是使用间谍作为拒绝处理程序,然后测试它被调用。