Тест Жасмин не пройден - PullRequest
       3

Тест Жасмин не пройден

0 голосов
/ 18 октября 2019

Я написал угловой тест для проверки кода httpstatus 0, возвращаемого, когда служба недоступна. Во время выполнения теста я получаю следующую ошибку. Какова возможная проблема здесь

Testing the interceptor class > making http calls > Adds a deliberate error code 0
Error: Expected undefined to equal 0.

Expected undefined to equal 'deliberate 0 error -  Unknown Error'.
Error: Expected undefined to equal 'deliberate 0 error -  Unknown Error'.

Обновление: я обновил код модульного теста, который включает определение класса перехватчика, который может помочь с диагностикой проблемы

Модульный тест

 import { TestBed, inject } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HTTP_INTERCEPTORS, HttpClient, HttpErrorResponse } from '@angular/common/http';
import { HttpWebInterceptor } from './httpWebInterceptor.service';

import { RouterTestingModule } from '@angular/router/testing';
import { OfflineComponent } from '../components/offline/offline.component';
import { Router } from '@angular/router';
import { AuthService } from '../services/auth.service';

import { Observable } from 'rxjs';
import { AlertService } from './alert.service';

class MockUser {
    clientCompanyId: number;
}

class MockAuthService  {
    get currentUser() : MockUser {
        let user = {clientCompanyId : 4};
        return user;
    }
}

class MockAlertService {
    resetStickyMessage() {

    }
}

describe('Testing the interceptor class', function () {

    let httpWebInterceptor: HttpWebInterceptor;
    let httpMock: HttpTestingController;
    let httpClient: HttpClient;   


    let routerSpy = { navigate: jasmine.createSpy('navigate') };

    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [
                OfflineComponent
            ],
            imports: [HttpClientTestingModule,
            RouterTestingModule.withRoutes([
                   { path: 'offline', component: OfflineComponent }
               ])
            ],
            providers: [HttpWebInterceptor,
                { provide: AlertService, useClass: MockAlertService },
                { provide: AuthService, useClass: MockAuthService },
                { provide: HTTP_INTERCEPTORS, useClass: HttpWebInterceptor, multi: true },               
                { provide: Router, useValue: routerSpy }
            ],

        });




        httpMock = TestBed.get(HttpTestingController);
        httpClient = TestBed.get(HttpClient);
        httpWebInterceptor = TestBed.get(HttpWebInterceptor);

    });



    describe('making http calls', () => {
        it('Adds a deliberate error code 0', inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {            

            spyOn(console, 'error');

            const fakeUrl = "http://localhost:57973/"; 
            const mockErrorResponse = { status: 0, statusText: 'deliberate 0 error -  Unknown Error' };
            const emsg = 'deliberate 0 error -  Unknown Error';
            let errResponse: any;

            http.get(fakeUrl).subscribe(
                (response) => {
                    fail('deliberate 0 error -  Unknown Error');
                },
                (error: HttpErrorResponse) => {                    
                    expect(error.status).toEqual(0, 'status');
                    expect(error.error).toEqual(emsg, 'message');
                });

            const req = httpMock.expectOne(fakeUrl);
            httpMock.verify();
            req.flush(emsg, { status: 0, statusText: 'Unknown Error' });
            expect(routerSpy.navigate).toHaveBeenCalledWith(['offline']);
            expect(console.error).toHaveBeenCalled();

        }));

    });



    describe('making http calls', () => {
        it('Adds a deliberate error code 404', inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {

            spyOn(console, 'error');

            const fakeUrl = "http://localhost:57973/";

            const emsg = 'deliberate 404 error - Not Found';

            http.get(fakeUrl).subscribe(
                (response) => {
                    fail('should have failed with the 404 error');
                },
                (error: HttpErrorResponse) => {
                    expect(error.status).toEqual(404, 'status');
                    expect(error.error).toEqual(emsg, 'message');
                });


            const req = httpMock.expectOne(fakeUrl);
            req.flush(emsg, { status: 404, statusText: 'Not Found' });

            // toHaveBeenCalledWith() looks at all the spy's calls. Use instead toEqual()
            expect(routerSpy.navigate).not.toEqual(['offline']);

            expect(console.error).toHaveBeenCalled();
        }));

    });



});

Обновление 2: класс перехватчика

import { Injectable, isDevMode } from '@angular/core';
import {
    HttpInterceptor,
    HttpRequest,
    HttpResponse,
    HttpHandler,
    HttpEvent,
    HttpErrorResponse
} from '@angular/common/http';
import { AuthService } from "../services/auth.service";
import { Observable, throwError } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { Router } from '@angular/router';
import { HttpStatusCode } from '../services/system-constants';
import { AlertService, MessageSeverity } from '../services/alert.service';

@Injectable()
export class HttpWebInterceptor implements HttpInterceptor {

    constructor(public router: Router,
        private authService: AuthService,
        private alertService: AlertService
    ) { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        if (!request.headers.has('Content-Type')) {
            request = request.clone({ headers: request.headers.set('Content-Type', 'application/json') });
        }

        return next.handle(request).pipe(
            map((event: HttpEvent<any>) => {
                if (event instanceof HttpResponse) {
                    console.log('event', event);
                    if(event.status == HttpStatusCode.OK)
                    {
                         if (this.router.url == '/offline') {
                             // Website is back online
                             console.log('redirecting to login');
                             this.authService.gotoLoginPage();
                        }
                    }
                }
                return event;
            }),
            catchError((error: HttpErrorResponse) => {
                if (error.error instanceof Error) {
                    // A client-side or network error occurred. Handle it accordingly.
                    if(isDevMode()) console.error('An error occurred:', error.error.message);
                } 
                else 
                {
                    if(isDevMode()) 
                        console.error('Backend returned code ${error.status}, body was: ${error.error}');

                    switch(error.status)
                    {
                        case HttpStatusCode.Unknown:
                        {
                            if (this.router.url != '/offline')
                            {

                                this.authService.clearUserData();
                                this.alertService.resetStickyMessage();
                                this.alertService.showMessage("No Network", "The server cannot be reached", MessageSeverity.error);
                                this.router.navigate(['offline']);
                                break;
                            } 
                        }
                        default:
                            break;
                    }
                }
                    return throwError(error);

            }));

    }
}

Обновление 3: классы имитации

class MockAuthService  {
    get currentUser() : MockUser {
        let user = {clientCompanyId : 4};
        return user;
    }

    clearUserData() {

    }
}

class MockAlertService {
    resetStickyMessage() {

    }

    showMessage() {

    }
}

1 Ответ

1 голос
/ 21 октября 2019

Полагаю, проблема в том, что MockAuthService & MockAlertService не полностью реализуют классы, которые они высмеивают. Например, MockAuthService.clearUserData() отсутствует в фиктивной реализации. Из-за этого должна быть ошибка времени выполнения в консоли браузера, и вы получите тест не пройден. Я воспроизвел проблему с теми же ошибками, что и у вас.

Вероятно, лучше реализовать макеты из исходных классов для получения ошибок компиляции, если некоторые функции отсутствуют, например:

class MockAuthService implements AuthService { ... }

Другой подход - использовать жасминовые насмешки. В этом случае компилятор не предупредит вас, если какой-либо метод отсутствует, но макет становится проще, например:

const authServiceMock = jasmine.createSpyObj<AuthService>(AuthService.name, [
    'gotoLoginPage',
    'clearUserData'
]);

Вы можете указать его следующим образом:

{ provide: AuthService, useValue: authServiceMock }

Каждый методв макете сейчас шпион, так что вы можете проверить его, как и другие шпионы, например:

expect(authServiceMock.gotoLoginPage).toHaveBeenCalled();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...