2017-10-28 6 views
1

Ich möchte einen Komponententest für meine Komponente schreiben, die Firestore verwendet, und ich stieß auf ein Problem mit Firebase Collection Mocking.Mocking Firestore-Sammlung in eckigen TestBed

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(); 
    }); 
}); 

Testlauf

Sobald ich den Test ausführen ich erhalte eine Fehlermeldung TypeError: this.db.collection is not a function

Von Stack-Trace-Informationen kann ich lesen, dass Fehler haben einen Ursprung in dieser Zeile und Zeichen this.db.**c**ollection<TObject>('tobjects').valueChanges()
in TobjectDatabase Klasse.

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) 

Was ist los? Wie könnte ich diese Sammlung verspotten?

Antwort

1

Ok, endlich habe ich es geschafft, Firestore-Sammlungen zu verspotten. Ich gebe ein Beispiel für unterschiedliche Service:

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']); 
    }); 

});