2017-10-12 4 views
0

Ich habe Service mit HttpClient mit einer POST-Anfrage, wenn der Server antwortet mit und Fehler muss ich es fangen formatieren Sie die Nachricht und werfen Sie es erneut. Ich habe versucht, dieses Szenario zu testen, habe es aber versäumt, den Test zu verspotten. Die HttpTestingController sendet nicht meine benutzerdefinierte Fehlermeldung zurück, noch wird es auf den Dienst zu kontrollieren und wieder werfen sie, Was ist der richtige Weg, um diesesTesten von Angular 4 HttpTestingController mit Catch und _throw Fehlerlogik

der Service-Code zu tun:

login(credentials: LoginPayload): Observable<LoginSuccessPayload> { 

     return this.http.post<LoginSuccessPayload>('/api/auth/signin', credentials) 
      .map(res => {authUser: res.user}) 
      .catch((error: HttpErrorResponse) => { 
       if (error.message) { 
        return _throw(error); 
       } 
       return _throw({message: 'Notification.LoginError'}); 
      }); 

} 

jetzt der Test

beforeEach(() => { 
    TestBed.configureTestingModule({ 
     imports: [HttpClientTestingModule], 
     providers: [AuthService] 
    }); 

    authService = TestBed.get(AuthService); 
    httpMock = TestBed.get(HttpTestingController); 
}); 

it('should format the error message', (done) => { 
    const credentials = {userName: 'bob', password: '123'} as LoginPayload; 
    const mockErrorResponse = {message: 'failed to login'} ; 

    authService.login(credentials).subscribe(() => {}, err => { 
     expect(err.message).toEqual(mockErrorResponse.message); 
     done(); 
    }); 

    const req = httpMock.expectOne('/api/auth/signin'); 
    req.error(new ErrorEvent(mockErrorResponse.message)); 

    httpMock.verify(); 
}); 

Antwort

0

Ich habe einige Vorschläge, die für mich ausgearbeitet haben.

Zunächst ich diese ersetzen würde:

mit diesem
authService = TestBed.get(AuthService); 
httpMock = TestBed.get(HttpTestingController); 

:

hier
const testBed = getTestBed(); 
authService = testBed.get(AuthService); 
httpMock = testBed.get(HttpTestingController); 

Ich denke, der Punkt ist, dass Sie nicht das Testbed tatsächlich zuzugreifen.

Ich würde auch Anzeige eine Überprüfung, dass Ihre Anfrage ist eine POST-Anfrage mit dem folgenden:

expect(req.request.method).toBe("POST"); 

Dies sind die Dinge, die ich auf den ersten Gedanken hinzufügen würde.

1

Ich weiß, dass ich zu spät dran bin, aber ich dachte, ich würde das trotzdem für jeden beantworten, der darüber stolpert wie ich. Ich finde die komplette lack of documentation auf angular.io um diesen Fehlerfall verrückt zu sein. "Finde es selbst heraus", schätze ich?

Wie dem auch sei ... der Ansatz, den ich war nahm .error() ganz zu vermeiden, da es nicht so einfach zu sein schien als .flush() verwenden und die Dokumentation tut state es für beide erfolgreiche und erfolglose Reaktionen verwendet werden können.

Hier ist, wie ich Ihren Code aktualisieren würde bündig verwenden:

it('should format the error message', (done) => { 
    const credentials = {userName: 'bob', password: '123'} as LoginPayload; 
    const mockErrorResponse = {message: 'failed to login'} ; 

    authService.login(credentials).subscribe(() => {}, err => { 
     // NOTE: err.error.message 
     expect(err.error.message).toEqual(mockErrorResponse.message); 
     done(); 
    }); 

    const req = httpMock.expectOne('/api/auth/signin'); 
    req.flush({message: mockErrorResponse.message}, {status: 400, statusText: ''}); 

    httpMock.verify(); 
}); 

Die eine ärgerliche Teil über dieses Update mit HttpClient in @angular/common/http wie in @angular/http zu Http Gegensatz ist, dass die Fehlermeldung ist jetzt eine Eigenschaft von err.error in der subscribe() anstatt err selbst.

Wenn Sie also wie ich sind und von einem auf den anderen aktualisieren, müssen alle Verweise auf err.message jetzt auf err.error.message aktualisiert werden. Ich hoffe das hilft.

+0

Ich mag Ihre Lösung, und es funktioniert auch für mich. Aber was bewirkt, dass flush() in Ihrem Code einen Fehler an den Abonnenten zurückgibt? Soll nicht req.error() aufgerufen werden, um einen Fehler zu emulieren? –

+0

@YakovFain Das zweite Argument von .flush(), das ein Objekt mit Eigenschaften wie dem Statuscode enthält. –

+0

Ich habe versucht, flush() mit dem Status 200, aber es geht immer noch an den Error-Handler des Abonnenten. Das funktioniert bei mir: '' 'req.error (new ErrorEvent ('Der Fehlertext')); ... .subscribe (() => {}, errorResponse => erwarten (errorResponse.error.type).toEqual ('Der Fehlertext') ); '' ' –