Я пытаюсь протестировать свое угловое приложение через Karma. Мое приложение подключено к базе данных firebase firestore. Я пытаюсь издеваться над коллекцией и использовать ее для проверки функций моих компонентов.
Фрагменты кода, которые я использую, следующие:
sprint.service.ts:
export class SprintService {
getSprints() {
return this.firestore.collection('sprints').snapshotChanges();
}
constructor(private firestore: AngularFirestore) { }
}
sprints.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;
})
});
}
sprints.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]);
}));
Я хочу, чтобы код работал без ошибок. Я, наверное, думаю, что мне нужно переписать метод getSprints
в моем MockSprintService. Кто-нибудь знает, что я должен вернуть или сгенерировать в методе getSprints()
, чтобы мой ngOnInit снова заработал? Помощь приветствуется.
В вашем издевательском методе getSprints() вы должны вернуть массив объектов со следующей структурой:
{ payload: { doc: { id: some_id }} }
потому что сейчас ваш e.payload не определен в вашем массиве издевательств.
Я вижу, вы импортируете и инициализируете AngularFireModule в своем модуле динамического тестирования. Это означает, что он фактически подключается к серверной части firebase каждый раз, когда вы запускаете тест... что обычно является очень плохой идеей. Что, если в ваших тестовых примерах нужно протестировать редактирование или удаление записей? Это означало бы, что они будут делать это каждый раз на реальных данных.
В идеале вы хотите издеваться над всеми своими зависимостями и максимально избегать импорта реальных (я знаю, что в мире Angular это не всегда возможно).
Одним из решений, которое я нашел для себя, является использование библиотеки ТС-мокито. Это позволяет вам с легкостью издеваться над классами, часто это работает из коробки. Некоторое время назад я написал сообщение в блоге, если вы хотите узнать больше: Издевательство над ts-mockito.
...
Вернемся к вашему конкретному примеру. Похоже, ваша фиктивная форма данных не соответствует тому, что возвращает служба firebase.
this.sprints = data.map(e => {
return {
id: e.payload.doc.id, //HERE IT ERRORS
...e.payload.doc.data()
} as Sprint;
})
Вы сопоставляете каждый элемент данных, и ожидается, что он будет иметь объект payload
с объектом doc
, который имеет свойство id
и метод data()
.
Однако в вашем MockSprintServce вы возвращаете наблюдаемое с массивом элементов с формой:
{
id: "1",
name:"TestSprint",
description:"TestSprint",
startDate:new Date(2000, 0, 1),
endDate:new Date(2001, 0, 1),
isActive:true
}
Это просто не соответствует. Если вы хотите продолжить текущую настройку и заставить ее работать, попробуйте изменить элементы в
getSprints(){
return of(...
к
[{
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})
}
}
}]
[ts] Левая часть оператора запятой не используется и не имеет побочных эффектов. [2695] по идентификатору, имени и описанию.
[ts] Не удается найти имя «isActive». [2304] на остальных 3 свойствах
Ой, простите. Я забыл поставить скобки вокруг возврата объекта функции стрелки. Попробуйте: data: () => ({id: "1", name: "TestSprint", description: "TestSprint", startDate: новая дата (2000, 0, 1), endDate: новая дата (2001, 0, 1) ), isActive:true})
Если я использую данные: () => как вы, это дает ошибки. У вас есть идеи, как вы можете сделать его Typo Proof?