我在这样的角度应用程序中有一个GeoLocationService
。
import { Injectable } from "@angular/core";
import { Observable } from "rxjs/Observable";
@Injectable()
export class GeoLocationService {
coordinates: any;
constructor() {}
public getPosition(): Observable<Position> {
return Observable.create(observer => {
navigator.geolocation.watchPosition((pos: Position) => {
observer.next(pos);
}),
() => {
console.log("Position is not available");
},
{
enableHighAccuracy: true
};
});
}
}
我想对该服务进行单元测试,以确保getPosition()
函数返回正常工作的Observable
。这是我的测试结果。
import { TestBed, fakeAsync } from "@angular/core/testing";
import { GeoLocationService } from "./geo-location.service";
import { take } from "rxjs/operators";
describe("GeoLocationService", () => {
let service: GeoLocationService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [GeoLocationService]
});
service = TestBed.get(GeoLocationService);
});
it("should get observable value", fakeAsync((done: DoneFn) => {
service
.getPosition()
.subscribe(value => {
expect(value.coords).not.toBeUndefined();
expect(value.coords).not.toBeNaN();
expect(value.coords).not.toBeNull();
done();
});
}));
});
这里发生的是,一旦我运行测试,测试就成功了(这是因为测试内部的subscribe
块尚未运行)。在打开的chrome browser window
(用于查看业力测试结果)上,我为应用程序选择Allow
以查找我的位置,此时subscribe
块正在运行,但到那时由于这个原因,it
规范已经完成。我得到console error
的话。
Uncaught Error: 'expect' was used when there was no current spec, this could be because an asynchronous test timed out
。
我不知道执行此测试的推荐方法是什么。如果有人可以帮助我,我将非常感激。
答案 0 :(得分:1)
您可以使用 it("should get observable value", fakeAsync((done: DoneFn) => {
let matchValue = {coords: null};
service
.getPosition()
.subscribe(value => {
matchValue = value;
});
tick(2000); // whatever fits your needs
expect(matchValue.coords).not.toBeUndefined();
expect(matchValue.coords).not.toBeNaN();
expect(matchValue.coords).not.toBeNull();
done();
}));
将测试伪装成同步的:-)
{emails.map((email, i) => (
<Grid item xs={12} sm={6}>
<TextField
className={classes.field}
id="contactEmails"
name="contactEmails"
label="Contact Email(s)"
fullWidth
// onChange={change.bind(null, 'contactEmails')}
autoComplete="lname"
inputProps={{
maxLength: 250
}}
value={emails[i]}
onChange={e => setEmails(
emails.map((email, j) => (i === j ? e.target.value : email))
)}
/>
</Grid>
))}
<Fab className={classes.addButton} style={{ marginRight: 10, marginBottom: 10, backgroundColor: '#3B70BC', color: 'white' }} onClick={() => setEmails([...emails, ''])}> <Add /> </Fab>
addButton: {
marginTop: theme.spacing.unit * 2,
color: '#3B70BC'
}
答案 1 :(得分:0)
我可以使用下面的代码来使其工作。
it("should get current user coordinates", (done: DoneFn) => {
let position: any;
service.getPosition().subscribe(value => {
position = value;
expect(position.coords).not.toBeUndefined();
expect(position.coords).not.toBeNaN();
expect(position.coords).not.toBeNull();
done();
});
});
为此,测试将一直等到您Allow
浏览器窗口获取您的位置。如果等待时间过长,将抛出timeOut错误。对我来说足够好,可以测试我想要的东西。