我有一个服务调用外部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' },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',> { name: 'City2',geonameId: 2}] > });