我有一个服务调用外部Web服务:
angular.module('myApp.services', [])
.service('autoCmpltDataSvc', function ($http) {
var innerMatch = function (data) {
return $.map(data, function (item) {
return {
fullName: item.name + (item.adminName1 ? ", " + item.adminName1 : "") + ", " + item.countryName,
shortName: item.name,
itemId: item.geonameId
};
});
};
this.fetchFromGeonamesDb = function (request, response, matcher) {
$http({
method: 'jsonp',
url: 'http://ws.geonames.org/searchJSON?callback=JSON_CALLBACK',
params: {
featureClass: "P",
style: "full",
maxRows: 12,
name_startsWith: request.destName
}
}).success(function (data, status) {
console.log(data);
response($.map(innerMatch(data.geonames), matcher));
});
};
});
我正在尝试测试它是否正确形成了输出,因此我模拟了对真实Web服务的调用.
这是我的单元测试.
describe('Services', function () {
beforeEach(module('myApp.services'));
describe('autoCompleteService', function () {
var $httpBackend, svc;
var results = [];
var matcher = function (item) {
return item;
};
var response = function (arr) {
results = arr;
};
beforeEach(inject(function ($injector, autoCmpltDataSvc) {
svc = autoCmpltDataSvc;
$httpBackend = $injector.get('$httpBackend');
$httpBackend.whenJSONP(/searchJSON/).
respond([
{ name: 'City1', adminName1: 'Region1', countryName: 'Country1', geonameId: 1 },
{ name: 'City2', countryName: 'Country2', geonameId: 2}]);
}));
afterEach(function () {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('should return values', function () {
$httpBackend.expectJSONP(/searchJSON/);
svc.fetchFromGeonamesDb({ 'destName': 'fra' }, response, matcher);
$httpBackend.flush();
expect(results.length).toBe(2);
});
});
});
但是测试会产生错误.
TypeError: Cannot read property 'length' of undefined
at Function.v.extend.map (C:/Users/kmukhort/Documents/_files/TMate/A
ngularTest/app/lib/jquery-1.8.3.min.js:2:15334)
at innerMatch (C:/Users/kmukhort/Documents/_files/TMate/AngularTest/
app/js/services.js:8:18)
我认为模拟响应有问题,因为它似乎没有返回数组.
但我无法理解为什么它不返回数组.
提前致谢!
最佳答案 由于彼得培根达尔文,我发现了一个愚蠢的错误.
OK so your success function is expecting your http call to return an
object with a field called geonames, currently your mock is returning
a straight array.Perhaps you should change your mock to this?
> $httpBackend.whenJSONP(/searchJSON/).
> respond( { geonames: [
> { name: 'City1', adminName1: 'Region1', countryName: 'Country1', geonameId: 1 },
> { name: 'City2', countryName: 'Country2', geonameId: 2}]
> });