用 TypeScript 编写的 Geocoder google 地图服务的业力异步测试
Asynchronous testing in karma for a Geocoder google maps service written in TypeScript
我记下了一个 Google 地图初始化程序服务,它在 dom 中加载 google 地图并公开 google 变量。我还编写了一个地理编码器服务,这是该服务的代码。
geoCodeAddress 方法是逻辑所在,其他部分只是 typescript 样板。当 mapService 公开 google 变量时,我利用它来定义方法并对给定地址进行地理编码,适当地返回供其他开发人员使用的承诺。
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);
}
我正在尝试使用以下代码测试服务,这主要是我的问题是如何正确测试它?我没有使用给定的代码。第二个测试失败,因为承诺没有解决并且期望 运行 更早,因此在错误中变得未定义。
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 周期,使用 setTimeout
和值 0。
并且因为 Angular 人知道这一点,他们创建了 $q 来包装 q 用于测试目的。
您所要做的就是:
rootScope.$apply();
活动更好,在afterEach
部分进行。
还有一件事(与问题无关),当在构造函数中定义 private/public/protected 成员时,TypeScript 将为您保存所做操作的样板文件。您的代码应如下所示:
export class GeoCoderService implements IGeoCoderService {
public geocoder: google.maps.Geocoder;
public static $inject = ['$q', 'GoogleMapsInitializerService'];
constructor(private q: angular.IQService, googleMaps: common.GoogleMapsInitializerService) {
}
.
.
.
我记下了一个 Google 地图初始化程序服务,它在 dom 中加载 google 地图并公开 google 变量。我还编写了一个地理编码器服务,这是该服务的代码。 geoCodeAddress 方法是逻辑所在,其他部分只是 typescript 样板。当 mapService 公开 google 变量时,我利用它来定义方法并对给定地址进行地理编码,适当地返回供其他开发人员使用的承诺。
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);
}
我正在尝试使用以下代码测试服务,这主要是我的问题是如何正确测试它?我没有使用给定的代码。第二个测试失败,因为承诺没有解决并且期望 运行 更早,因此在错误中变得未定义。
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 周期,使用 setTimeout
和值 0。
并且因为 Angular 人知道这一点,他们创建了 $q 来包装 q 用于测试目的。
您所要做的就是:
rootScope.$apply();
活动更好,在afterEach
部分进行。
还有一件事(与问题无关),当在构造函数中定义 private/public/protected 成员时,TypeScript 将为您保存所做操作的样板文件。您的代码应如下所示:
export class GeoCoderService implements IGeoCoderService {
public geocoder: google.maps.Geocoder;
public static $inject = ['$q', 'GoogleMapsInitializerService'];
constructor(private q: angular.IQService, googleMaps: common.GoogleMapsInitializerService) {
}
.
.
.