2014-03-06 28 views
3

我正在測試使用Google Maps Geoencoding服務的服務。認爲它會很容易,因爲它非常簡單直接的代碼。但似乎不是。

這裏的服務:

(function() { 
    'use strict'; 

    var GoogleGeocodingService = function ($q, GoogleAPILoaderService, $rootScope) { 

     var geocoder, 
      mapsReadyPromise; 

     mapsReadyPromise = GoogleAPILoaderService.load('maps', '3', {other_params: 'sensor=false'}).then(function() { 
      geocoder = new google.maps.Geocoder(); 
     }); 

     var getLatLng = function (searchKeyword) { 
      var deferred = $q.defer(); 

      mapsReadyPromise.then(function() { 
       geocoder.geocode({'address': searchKeyword}, function (results, status) { 
        $rootScope.$apply(function() { 
         if (status === google.maps.GeocoderStatus.OK) { 
          deferred.resolve(results); 
         } else { 
          deferred.reject(status); 
         } 
        }); 
       }); 
      }); 

      return deferred.promise; 
     }; 

     return { 
      getLatLng: getLatLng 
     }; 

    }; 

    app.factory('GoogleGeocodingService', ['$q', 'GoogleAPILoaderService', '$rootScope', GoogleGeocodingService]); 
}()); 

爲了在不使用真正的google.maps我嘲笑兩個GoogleAPILoaderService和google.maps

但是,當我嘗試測試它時,我進入了$digest already in progress。我用safeApply嘗試過,但不起作用。

it('Should call geocoder.geocode to retrieve results', function() { 
    GoogleGeocoding.getLatLng('Canada'); 
    $rootScope.$apply(); 
    expect(GeoCoderMock.prototype.geocode).toHaveBeenCalledWith({ address : 'Canada'}); 
}); 

這是全規格:

(function() { 
    "use strict"; 
    var GeoCodingOK, GeoCodingError, GeoCoderMock, GoogleAPILoaderMock, $rootScope, $q, $timeout, GoogleGeocoding; 

    describe('Google Geocoding Service', function() { 

     beforeEach(angular.mock.module('app', function($provide){ 
      GoogleAPILoaderMock = jasmine.createSpyObj('GoogleAPILoaderService',['load']); 
      $provide.value('GoogleAPILoaderService',GoogleAPILoaderMock); 
     })); 

     beforeEach(inject(function (_$q_,_$rootScope_) { 
      $q = _$q_; 
      $rootScope = _$rootScope_; 

      GoogleAPILoaderMock.load.andCallFake(function() { 
       var deferred = $q.defer(); 
       deferred.resolve('Library Loaded');    
       return deferred.promise; 
      }); 
     })); 

     beforeEach(inject(function (GoogleGeocodingService) { 
      GoogleGeocoding = GoogleGeocodingService; 

      window.google = jasmine.createSpy('google'); 
      window.google.maps = jasmine.createSpy('maps'); 
      window.google.maps.GeocoderStatus = jasmine.createSpy('GeocoderStatus'); 
      window.google.maps.GeocoderStatus.OK = 'OK'; 

      GeoCodingOK = function (params, callback) { 
       callback({data: 'Fake'}, 'OK'); 
      }; 

      GeoCodingError = function (params, callback) { 
       callback({data: 'Fake'}, 'ERROR'); 
      }; 

      GeoCoderMock = window.google.maps.Geocoder = jasmine.createSpy('Geocoder'); 
      GeoCoderMock.prototype.geocode = jasmine.createSpy('geocode').andCallFake(GeoCodingOK); 
     })); 

     it('Should expose some functions', function(){ 
      expect(typeof GoogleGeocoding.getLatLng).toBe('function'); 
     }); 
     describe('getLatLng function', function() { 
      it('Shouldn\'t call anything if the promise hasn\'t been resolved', function() { 
       GoogleGeocoding.getLatLng('Canada'); 
       expect(GeoCoderMock.prototype.geocode).not.toHaveBeenCalled(); 
      }); 
      it('Should return a promise', function() { 
       var promise = GoogleGeocoding.getLatLng('Canada'); 
       expect(typeof promise.then).toBe('function'); 
      }); 
      it('Should call geocoder.geocode to retrieve results', function() { 
       GoogleGeocoding.getLatLng('Canada'); 
       $rootScope.$apply(); 
       expect(GeoCoderMock.prototype.geocode).toHaveBeenCalledWith({ address : 'Canada'}); 
      }); 
      it('Should resolve the promise when receiving data', function() { 
       var okMock = jasmine.createSpy(); 
       GoogleGeocoding.getLatLng('Canada').then(okMock); 
       $rootScope.$apply(); 
       expect(okMock).toHaveBeenCalledWith({ address : 'Canada'}); 
      }); 
     }); 
    }); 
}()); 

FAQ

  • 你試過$$phase檢查?

是的。不起作用。不知何故,該階段在那一點是空的。我擔心通過調用$apply我正在釋放其中兩個如何,這是造成這個問題。

  • 你能爲此提供一個Plunker嗎?

當然是的!鏈接到Plunker

回答

4

問題很簡單。 mapsReadyPromise裏面的$apply不需要,所以當你在測試上做另一個$apply時,它會變得瘋狂。去除$apply解決$digest問題,那麼你只需要解決幾個問題,並準備:)

http://plnkr.co/edit/wRdJNqAk9RZ7vg3Dli6K?p=preview

+0

感謝您的! –

相關問題