用TypeScript编写的Geocoder谷歌地图服务的因果报应异步测试

Asynchronous testing in karma for a Geocoder google maps service written in TypeScript

本文关键字:服务 因果报应 异步 测试 谷歌地图 Geocoder TypeScript      更新时间:2023-09-26

我写了一个Google Maps Initializer服务,它在dom中加载Google地图并公开Google变量。我还编写了一个地理编码服务,下面是该服务的代码。geoCodeAddress方法是逻辑所在的地方,其他部分只是typescript样板。当mapService公开google变量时,我利用它来定义方法并对给定地址进行地理编码,从而适当地返回promise供其他开发人员使用。

module portal.common {
    export interface IGeoCoderService {
        geoCodeAddress(address: string): angular.IPromise<google.maps.GeocoderResult>;
    }
    export class GeoCoderService implements IGeoCoderService {
        public static $inject = ['$q', 'GoogleMapsInitializerService'];
        private $q: angular.IQService;
        public mapService: common.GoogleMapsInitializerService;
        public geocoder: google.maps.Geocoder;
        constructor(private q: angular.IQService, googleMaps: common.GoogleMapsInitializerService) {
            this.mapService = googleMaps;
            this.$q = q;
        }
        public geoCodeAddress(address: string) {
            return this.mapService.init()
                .then(() => {
                    this.geocoder = new google.maps.Geocoder();
                    let deferred = this.$q.defer();
                    this.geocoder.geocode({ address: address }, (results: Array<google.maps.GeocoderResult>, status: google.maps.GeocoderStatus) => {
                        if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
                            deferred.resolve(results);
                        } else {
                            deferred.reject({
                                data: 'No Results'
                            });
                        }
                    });
                    return deferred.promise;
                });
        }
    }
    angular.module('olCommon').service('GeoCoderService', GeoCoderService);
}

我正在尝试使用以下代码测试服务,这主要是我的问题是如何正确测试它?我使用给定的代码失败了。第二个测试失败,因为promise没有得到解决,预期运行得更早,因此在错误中未定义。

describe('GeoCoderService', function () {
    var GeoCoderService, $timeout;
    beforeEach(module('olCommon'));
    beforeEach(function () {
        inject(function (_GeoCoderService_, _$timeout_) {
            GeoCoderService = _GeoCoderService_;
            $timeout = _$timeout_;
            spyOn(GeoCoderService, 'geoCodeAddress').and.callThrough();
        });
    });
    it('should initialize correctly', function () {
        expect(GeoCoderService).toBeDefined();
    });
    it('should geocode the address correctly', function () {
        var address = 'Unit 11 35, Crown Street, Granville, NSW 2142';
        var results = undefined;
        GeoCoderService.geoCodeAddress(address).then(function (response) {
            results = response;
        });
        expect(results).toBeDefined();
    });
});

因为q永远不会立即调用then,所以它实际上在等待下一个javascript周期,使用值为0的setTimeout

因为Angular的人知道这一点,他们创建了$q,用于测试目的。

你所要做的就是:

rootScope.$apply();

事件更好,请在afterEach部分中执行。

还有一件事(与问题无关),当在构造函数中定义私有/公共/受保护的成员时,TypeScript将为您保存所做操作的样板。你的代码应该是这样的:

export class GeoCoderService implements IGeoCoderService {
  public geocoder: google.maps.Geocoder;
  public static $inject = ['$q', 'GoogleMapsInitializerService'];
  constructor(private q: angular.IQService, googleMaps: common.GoogleMapsInitializerService) {
  }
  .
  .
  .