Angular 无法读取属性';doc&x27;通过间谍/业力模拟服务等级时的未定义属性
我试图通过业力来测试我的角度应用。我的应用程序已连接到firebase firestore数据库。我试图模拟一个集合,并使用它来测试我的组件功能 我正在使用的代码段如下所示: sprint.service.ts:Angular 无法读取属性';doc&x27;通过间谍/业力模拟服务等级时的未定义属性,angular,firebase,testing,karma-jasmine,spy,Angular,Firebase,Testing,Karma Jasmine,Spy,我试图通过业力来测试我的角度应用。我的应用程序已连接到firebase firestore数据库。我试图模拟一个集合,并使用它来测试我的组件功能 我正在使用的代码段如下所示: sprint.service.ts: export class SprintService { getSprints() { return this.firestore.collection('sprints').snapshotChanges(); } constructor(private fir
export class SprintService {
getSprints() {
return this.firestore.collection('sprints').snapshotChanges();
}
constructor(private firestore: AngularFirestore) { }
}
sprint.component.ts
sprints : Sprint[];
constructor(private sprintService: SprintService) { }
ngOnInit() {
this.sprintService.getSprints().subscribe(data => {
this.sprints = data.map(e => {
return {
id: e.payload.doc.id, //HERE IT ERRORS
...e.payload.doc.data()
} as Sprint;
})
});
}
sprint.component.spec.ts
//Mock class
class MockSprintServce
{
getSprints(){
return of([
{id: "1", name:"TestSprint", description:"TestSprint", startDate:new Date(2000, 0, 1), endDate:new Date(2001, 0, 1), isActive:true},
{id: "2", name:"TestSprint2", description:"TestSprint2", startDate:new Date(2000, 0, 1), endDate:new Date(2001, 0, 1), isActive:false},
])
}
}
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ FormsModule, AngularFireModule.initializeApp(environment.firebase) ],
declarations: [ ArchivedUserstoriesComponent,SprintDetailComponent, SprintsComponent, UserDetailComponent, UsersComponent, UserstoriesComponent, UserstoryDetailComponent ],
providers: [AngularFirestore, {provide: SprintService, useClass: MockSprintServce}]
})
.compileComponents();
}));
beforeEach(() => {
app.sprints = [
{id: "1", name:"TestSprint", description:"TestSprint", startDate:new Date(2000, 0, 1), endDate:new Date(2001, 0, 1), isActive:true},
{id: "2", name:"TestSprint2", description:"TestSprint2", startDate:new Date(2000, 0, 1), endDate:new Date(2001, 0, 1), isActive:false},
]
});
it(`should return all Sprints`, async(() => {
//arrange
let getSpy = spyOn(mockSprintServiceObject, 'getSprints').and.returnValue({ subscribe: () => {} });
//act
app.ngOnInit({});
//assert
expect(getSpy).toHaveBeenCalled();
expect(getSpy).toContain(app.sprints[1]);
}));
我希望代码能够正常工作,没有任何错误。我可能认为我必须重写mocksprint服务中的getSprints
方法。有人知道我应该在getSprints()
方法中返回或生成什么来让我的ngOnInit再次工作吗?非常感谢您的帮助。在模拟的getSprints()方法中,您应该返回具有以下结构的对象数组:
{ payload: { doc: { id: some_id }} }
因为现在您的模拟数组中没有定义e.payload。我看到您正在动态测试模块中导入并初始化AngularFireModule。这意味着每次运行测试时,它实际上都会连接到firebase后端。。这通常是一个非常糟糕的主意。如果您的测试用例需要测试编辑或删除条目,该怎么办?这意味着他们每次都会根据实际数据来做 理想情况下,您希望模拟所有依赖项,并尽可能避免导入真实的依赖项(我知道在角度世界中,这并不总是可能的) 我为自己找到的一个解决方案是使用图书馆。它允许您轻松地模拟类—通常它是开箱即用的。如果您想了解更多信息,我不久前写了一篇博文: 回到你的具体例子。您的模拟数据形状似乎与firebase服务返回的不匹配
this.sprints = data.map(e => {
return {
id: e.payload.doc.id, //HERE IT ERRORS
...e.payload.doc.data()
} as Sprint;
})
您映射每个数据项,它应该有一个带有doc
对象的payload
对象,该对象具有id
属性和data()
方法
但是,在MockSprintServe中,您返回一个可观察的带有形状的项目数组:
{
id: "1",
name:"TestSprint",
description:"TestSprint",
startDate:new Date(2000, 0, 1),
endDate:new Date(2001, 0, 1),
isActive:true
}
就是不匹配。
如果要继续使用当前设置并使其正常工作,请尝试更改当前设置中的项目
getSprints(){
return of(...
到
如果我像你一样使用数据:()=>它会给出错误。您知道如何使其防打字吗?[ts]逗号运算符的左侧未使用,并且没有副作用。[2695]在id、名称和说明上。[ts]找不到名称“isActive”。[2304]关于其他三项财产哦,对不起。我忘了在arrow函数对象return的周围加上括号。Try:data:()=>({id:“1”,name:“TestSprint”,description:“TestSprint”,startDate:new Date(2000,0,1),endDate:new Date(2001,0,1),isActive:true})
[{
payload: {
doc: {
id: '1',
data: () => ({id: "1", name:"TestSprint", description:"TestSprint", startDate:new Date(2000, 0, 1), endDate:new Date(2001, 0, 1), isActive:true})
}
}
}]