[英]Mocking Firestore collection in angular TestBed
I'd like to write a unit test for my component which uses Firestore and I encountered an issue with Firebase collection mocking.我想为使用 Firestore 的组件编写单元测试,但遇到了 Firebase 集合模拟问题。
SUT SUT
export class TobjectsListComponent implements OnInit {
...
constructor(private db: AngularFirestore) {
this.tobjectDatabase = new TobjectDatabase(db);
}
...
}
export class TobjectDatabase {
/** Stream that emits whenever the data has been modified. */
dataChange: BehaviorSubject<TObject[]> = new BehaviorSubject<TObject[]>([]);
get data(): TObject[] { return this.dataChange.value; }
constructor(private db: AngularFirestore) {
this.db.collection<TObject>('tobjects').valueChanges()
.subscribe(data => { this.dataChange.next(data); });
}
}
TEST测试
class AngularFirestoreMock extends AngularFirestore {
public collection<TObject>(name: string, queryFn?: QueryFn): AngularFirestoreCollection<TObject> {
const ref = this.firestore.collection('tobjects');
if (!queryFn) { queryFn = (ref) => ref; }
return new AngularFirestoreCollection<TObject>(ref, queryFn(ref));
}
}
describe('TobjectListComponent', () => {
let component: TobjectsListComponent;
let fixture: ComponentFixture<TobjectsListComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MaterialModule],
declarations: [TobjectsListComponent],
providers: [{ "provide": AngularFirestore, "useValue": AngularFirestoreMock }],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TobjectsListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
Test run试运行
Once I run the test I get an error TypeError: this.db.collection is not a function
一旦我运行测试,我得到一个错误
TypeError: this.db.collection is not a function
From stack trace info I can read that error have an origin in this line and character this.db.**c**ollection<TObject>('tobjects').valueChanges()
从堆栈跟踪信息中,我可以读取该错误在这一行中的起源和字符
this.db.**c**ollection<TObject>('tobjects').valueChanges()
in TobjectDatabase
class.在
TobjectDatabase
类中。
TypeError: this.db.collection is not a function
at new TobjectDatabase (http://localhost:9876/_karma_webpack_/webpack:/C:/git/volago2/src/app/tobjects-admin/tobjects-list/tobjects-list.component.ts:82:13)
at new TobjectsListComponent (http://localhost:9876/_karma_webpack_/webpack:/C:/git/volago2/src/app/tobjects-admin/tobjects-list/tobjects-list.component.ts:24:28)
at createClass (http://localhost:9876/_karma_webpack_/webpack:/C:/git/volago2/node_modules/@angular/core/@angular/core.es5.js:10933:1)
at createDirectiveInstance (http://localhost:9876/_karma_webpack_/webpack:/C:/git/volago2/node_modules/@angular/core/@angular/core.es5.js:10764:22)
at createViewNodes (http://localhost:9876/_karma_webpack_/webpack:/C:/git/volago2/node_modules/@angular/core/@angular/core.es5.js:12212:34)
at createRootView (http://localhost:9876/_karma_webpack_/webpack:/C:/git/volago2/node_modules/@angular/core/@angular/core.es5.js:12107:1)
at callWithDebugContext (http://localhost:9876/_karma_webpack_/webpack:/C:/git/volago2/node_modules/@angular/core/@angular/core.es5.js:13493:26)
at Object.debugCreateRootView [as createRootView] (http://localhost:9876/_karma_webpack_/webpack:/C:/git/volago2/node_modules/@angular/core/@angular/core.es5.js:12810:1)
at ComponentFactory_.webpackJsonp.../../../core/@angular/core.es5.js.ComponentFactory_.create (http://localhost:9876/_karma_webpack_/webpack:/C:/git/volago2/node_modules/@angular/core/@angular/core.es5.js:9872:26)
at initComponent (http://localhost:9876/_karma_webpack_/webpack:/C:/git/volago2/node_modules/@angular/core/@angular/core/testing.es5.js:889:1)
What's wrong?怎么了? How could I mock this collection?
我怎么能嘲笑这个集合?
Ok, I finally have managed mocking of Firestore collections.好的,我终于成功地模拟了 Firestore 集合。 I give an example of different service:
我举一个不同服务的例子:
SUT SUT
import { Injectable } from '@angular/core';
import { AngularFirestore } from 'angularfire2/firestore';
import { Administrative } from '../model/administrative';
@Injectable()
export class AdministrativeService {
administratives: Administrative[] = [];
constructor(private db: AngularFirestore) {
this.db.collection<Administrative>('administrative').valueChanges()
.subscribe(data => this.administratives = data);
}
getPath(uname: string): string[] {
let current = this.administratives.find((a: Administrative) => a.uname === uname);
const result: string[] = [current.name];
while (current.parent) {
current = this.administratives.find((a: Administrative) => a.uname === current.parent);
result.unshift(current.name);
}
return result;
}
}
TEST测试
import { TestBed, inject } from '@angular/core/testing';
import { AdministrativeService } from './administrative.service';
import { AngularFirestore } from 'angularfire2/firestore';
import { Observable } from 'rxjs/Rx';
import { Administrative } from '../model/administrative';
const input: Administrative[][] = [[
{ name: 'Polska', uname: 'polska', parent: ''},
{ name: 'Dolnośląskie', uname: 'dolnoslaskie', parent: 'polska'},
{ name: 'Wrocław', uname: 'wroclaw', parent: 'dolnoslaskie'}
]];
const data = Observable.from(input);
const collectionStub = {
valueChanges: jasmine.createSpy('valueChanges').and.returnValue(data)
}
const angularFiresotreStub = {
collection: jasmine.createSpy('collection').and.returnValue(collectionStub)
}
describe('AdministrativeService', () => {
let service: AdministrativeService;
let angularFirestore: AngularFirestore;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
AdministrativeService,
{ provide: AngularFirestore, useValue: angularFiresotreStub }
]
});
service = TestBed.get(AdministrativeService);
angularFirestore = TestBed.get(AngularFirestore);
});
it('should be created', () => {
expect(service).toBeTruthy();
expect(angularFiresotreStub.collection).toHaveBeenCalledWith('administrative');
});
it('gets hierarchy path', () => {
const result = service.getPath('wroclaw');
expect(result).toEqual(['Polska', 'Dolnośląskie', 'Wrocław']);
});
});
A pattern that worked in my case在我的情况下有效的模式
Service:服务:
import { AngularFirestore } from '@angular/fire/firestore';
public db: AngularFirestore // in constructor
updateArticle(someId, data) {
this.db.collection('articles').doc(someId).update({ some: data });
}
Test:测试:
const updateSpy: Spy = jasmine.createSpy('update');
spyOn(service.db, 'collection').and.returnValue({
doc: (data: any): any => {
return {
update: updateSpy,
};
},
});
service.updateArticles('123', 'lol');
expect(service.db.collection).toHaveBeenCalledWith('articles');
expect(updateSpy).toHaveBeenCalledWith({ some: 'lol' });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.