如何测试与Firebase交互的服务?

Ell*_*son 3 firebase firebase-realtime-database angularfire2 angular

从Firebase获取数据的惯例似乎是创建一个在内部使用AngularFire的服务类.然后,在您的应用程序的组件中,您可以注入并使用该服务.这使您可以在单元测试组件时轻松模拟服务.

但是,我仍然不清楚如何测试实际的服务本身.

举个例子,假设我todo list在Firebase中有一个节点,我有一个简单的服务来抓取所有的节点todos,如下所示:

import { Injectable } from '@angular/core';
import { AngularFire } from 'angularfire2';

@Injectable()
export class TodoService {
  constructor(private af: AngularFire) { }

  getAll(): FirebaseListObservable<any[]> {
    return this.af.database.list('todos');
  }
}
Run Code Online (Sandbox Code Playgroud)

您将如何测试此服务是否符合您的期望?

Ell*_*son 6

Reaz在他的回答中推荐了MockFirebase.但是,MockFirebase不能与Firebase 3一起使用.有一个名为firebase-mock的库,它似乎是由一些与MockFirebase相同的人开发的.这增强了MF,增加了对Firebase 3的支持,但它似乎还没有与WebPack很好地兼容.

这是我最终做的事情:

FirebaseListObservable突然想到继承自RXJS的Observable.所以,你可以模拟出AngularFire调用list并让它返回你自己的Observable.

一些示例代码显示了这一点:

todos.service.spec.ts

let fixtureTodos = [
  { 'text': 'Get milk' },
  { 'text': 'Take out the trash' },
  { 'text': 'Get gas for the car' },
  { 'text': 'Pay parking ticket' },
  { 'text': 'Pick up dry cleaning' },
];
let angularFireDatabaseStub = { list: () => {} };
let mockTodos$ = Observable.of(fixtureTodos);

describe('TodosService', () => {
  beforeEach(() => {
    spyOn(angularFireDatabaseStub, 'list').and.returnValue(mockTodos$);

    TestBed.configureTestingModule({
      providers: [
        TodosService,
        { provide: AngularFireDatabase, useValue: angularFireDatabaseStub },
      ]
    });
  });

  it('#getAll', inject([TodosService], (service: TodosService) => {
    let todos$ = service.getAll();
    todos$.subscribe(todos => {
      expect(todos[0].text).toEqual(fixtureTodos[0].text);
      expect(todos[0]).toEqual(jasmine.any(Todo));
    });
  }));
});
Run Code Online (Sandbox Code Playgroud)

todos.service.ts

@Injectable()
export class TodosService {
  constructor(public db: AngularFireDatabase) { }

  getAll(): Observable<Todo[]> {
    return this.db.list('todos').map(arr => {
      return arr.map(t => new Todo(t.text));
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

todo.model.ts

export class Todo {
  constructor(public text: string) {}
}
Run Code Online (Sandbox Code Playgroud)