2016-11-14 7 views
2

Ich bin neu in der Testwelt und ich habe gerade angefangen, Komponententests für einen vorhandenen Angular 2 Code zu schreiben. Ich habe eine Funktion confirmDelete, die Obserable<boolean> zurückgibt und intern ConfirmationService von PrimeNG verwendet, um das Feedback des Benutzers auf einem Popup zu erhalten.Unit Tests Winkel Observables

Definition der Funktion ist unten angegeben:

confirmDelete(): Observable<boolean> { 
    let confirmObservable = Observable.create((observer: Observer<boolean>) => {    
     this.confirmationService.confirm({ 
      header: 'Delete Confirmation', 
      message: 'Do you really want to delete this record?', 
      accept:() => { 
       observer.next(true); 
       observer.complete();    
      }, 
      reject:() => { 
       observer.next(false); 
       observer.complete(); 
      } 
     }); 

    }); 

    return confirmObservable; 

} 

ich einen Komponententest für dieses Stück Code schreiben möchten. Ich plante, einen Stub für die ConfirmationService zu schreiben, aber weil ich neu in der Unit-Test-Welt bin, finde ich es schwierig, die Dinge einzurichten.

Meine Frage ist, was ist der richtige Ansatz, um einen Komponententest in diesem bestimmten Szenario zu schreiben.

EDIT: -

versuchte ich Lösung von @peeskillet vorgeschlagen, aber dann begann ich Typenkonfliktfehler zwischen ConfirmationService und MockConfirmationService bekommen.

Unten sind die Deklarationen ConfirmationService und Confirmation Klassen in der PrimeNG-Bibliothek gefunden.

export interface Confirmation { 
    message: string; 
    icon?: string; 
    header?: string; 
    accept?: Function; 
    reject?: Function; 
    acceptVisible?: boolean; 
    rejectVisible?: boolean; 
    acceptEvent?: EventEmitter<any>; 
    rejectEvent?: EventEmitter<any>; 
} 
export declare class ConfirmationService { 
    private requireConfirmationSource; 
    private acceptConfirmationSource; 
    requireConfirmation$: Observable<Confirmation>; 
    accept: Observable<Confirmation>; 
    confirm(confirmation: Confirmation): this; 
    onAccept(): void; 
} 

Antwort

3

Ich würde wahrscheinlich das Mock hält, macht auf die Referenzen der accept und reject Funktionen. Dann können Sie sie im Test aufrufen, um zu überprüfen, ob sie den korrekten booleschen Wert ausgeben. So etwas wie

class MockConfirmationService { 
    accept: Function; 
    reject: Function; 

    confirm(config: any) { 
    this.accept = config.accept; 
    this.reject = config.reject; 
    } 
} 

Dann in Ihrem Test rufen Sie einfach die accept zu testen, dass true emittiert wird, und rufen reject zu testen, dass false emittiert wird.

describe('serivce: ModalService',() => { 

    let modalService: ModalService; 
    let confirmService: MockConfirmationService; 

    beforeEach(() => { 
    confirmService = new MockConfirmationService(); 
    TestBed.configureTestingModule({ 
     providers: [ 
     ModalService, 
     { provide: ConfirmationService, useValue: confirmService } 
     ] 
    }); 

    modalService = TestBed.get(ModalService); 
    }); 

    it('should return true when accepted', async(() => { 
    modalService.confirmDelete().subscribe(result => { 
     expect(result).toBe(true); 
     console.log('accepted test complete'); 
    }); 
    confirmService.accept(); 
    })); 

    it('should return false when rejected', async(() => { 
    modalService.confirmDelete().subscribe(result => { 
     expect(result).toBe(false); 
     console.log('rejected test complete'); 
    }); 
    confirmService.reject(); 
    })); 
}); 
+0

Danke @ Peeskillet. Ich habe die obige Lösung ausprobiert, aber ich erhalte einige Typ-Mismatch-Fehler. Bitte beachten Sie meinen oben veröffentlichten Beitrag. –

+0

Ich sollte arbeiten. Ich habe es getestet und es funktioniert gut. Schau dir mein Beispiel genau an. 'ModalService' ist nichts anderes als eine einfache Klasse, die den' ConfirmationService' als Konstruktorparameter verwendet. Und die Methode, ich kopiere und klebte stright aus deinem Beitrag –

+0

Wenn Sie versuchen, den Test ohne TestBed zu tun (nur Instantiierung des Dienstes im Test, und übergibt die Mock, um es Konstruktor), dann müssen Sie die "werfen" vor dem Versuch, es zu überspielen. Aber mit dem Testbed müssen wir uns über diese Dinge keine Gedanken machen, da die Typprüfung nur zur Kompilierzeit ist. –

0

Ich habe von peeskillet's Antwort gebaut. Die p-confirmDialog Komponente ruft die von dem Dienst anmelden, also musste ich hinzugefügt requireConfirmationSource, die ich in der PrimeNg Quelle gefunden. Mein Schein ist wie folgt:

// 
import { Subject } from 'rxjs/Subject'; 
import { Observable } from 'rxjs/Observable'; 
// 
export class ConfirmationServiceMock { 
    public key: string = 'mock1'; 
    public header: string = 'Delete Confirmation'; 
    public icon: string = ''; 
    public message: string = ''; 
    // Call Accept to emulate a user accepting 
    public accept: Function; 
    // Call Reject to emulate a user rejecting 
    public reject: Function; 
    private requireConfirmationSource = new Subject<any>(); 
    requireConfirmation$ = this.requireConfirmationSource.asObservable(); 
    // 
    public confirm(config: any) { 
     console.log('In confirm service mock...'); 
     this.message = config.message; 
     this.accept = config.accept; 
     this.reject = config.reject; 
     console.log(this.message); 
     return this; 
    } 
} 
//