Модульное тестирование службы с использованием Angular 6 HttpTestingController

У меня есть служба Angular v6, которая вызывает основной API .net и получает большой двоичный объект, представляющий собой PDF-файл. Когда он получает ответ OK от API, служба также устанавливает флаг в значение true, который используется компонентом.

Я пытаюсь написать модульный тест Jasmine для этого поведения, и он продолжает сообщать, что флаг ложный (но предлагает мне загрузить поддельный файл). Karma сообщает: Expected undefined to be truthy. При использовании развернутого кода все выглядит правильно, поэтому я считаю, что это ошибка в модульном тесте.

Это мое первое приложение на Angular 6, использующее Typescript, так что это может быть ошибка в чем-то более простом.

Обслуживание:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { saveAs } from 'file-saver';
import { environment } from '../environments/environment';

import { InputParameters } from './inputParameters';

@Injectable({
    providedIn: 'root'
})
export class SettlementService
{
    success: boolean;
    private apiUrl = environment.apiURL;

    constructor(private http: HttpClient) { }

    getSettlement(inputParms: InputParameters, captchaResponse: string)
    {
        //add captcha response header
        let headers: HttpHeaders = new HttpHeaders();
        headers = headers.append('g-recaptcha-response', captchaResponse);

        //submit post request to service layer
        return this.http
            .post(this.apiUrl, inputParms, { responseType: 'blob', observe: 'response', headers: headers })
            .toPromise()
            .then(response =>
            {
                this.success = true;
                this.saveToFileSystem(response);
            })
            .catch((reason: Response) =>
            {
                this.success = false;
                console.info(reason);
                //alert("Settlement not found!");
            });
    }

    private saveToFileSystem(response)
    {
        //get the file name from the content-disposition header
        const contentDispositionHeader: string = response.headers.get('Content-Disposition');
        const parts: string[] = contentDispositionHeader.split(';');
        const fileName = parts[1].split('=')[1];

        const blob = new Blob([response.body], { type: 'application/pdf' });

        saveAs(blob, fileName);
    }
}

Модульный тест сервиса, который я тестирую:

import { TestBed, inject, getTestBed, tick, fakeAsync } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';

import { SettlementService } from './settlement.service';
import { InputParameters } from './inputParameters';

describe('SettlementService', () =>
{
    let injector: TestBed;
    let service: SettlementService;
    let httpMock: HttpTestingController;

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

        injector = getTestBed();
        service = injector.get(SettlementService);
        httpMock = injector.get(HttpTestingController);
    });

    afterEach(() =>
    {
        httpMock.verify();
    });

    it('should download a file and success should be true', (() =>
    {
        //arrange
        //return blob
        const file = new Blob(['ATESTFILE'], { type: 'application/pdf' });

        //setup input parms
        let parms: InputParameters = new InputParameters();
        parms.agreementNumber = '001234567898';
        parms.bankAccountNumber = '00112233';
        var date: Date = new Date();
        date.setFullYear(date.getFullYear() - 20);
        parms.dateOfBirth = date;

        //act
        service.getSettlement(parms, '0000000');

        //assert
        expect(service.success).toBeTruthy();

        const req = httpMock
            .expectOne('http://localhost:5000/api/settlement');
        expect(req.request.headers.has('g-recaptcha-response'));
        expect(req.request.method).toEqual('POST');

        //act
        req.flush(file, {
            headers: { 'Content-Disposition': 'attachment; filename = "testfilename.pdf"' },
            status: 200,
            statusText: 'OK'
        });
    }));

Опубликуйте вывод полученной ошибки. Тест выглядит неплохо.

bc1105 31.07.2018 15:25

добавил его в q, но его Expected undefined to be truthy.

cjb110 31.07.2018 15:39

Я думаю, вам нужно подождать, пока служба разрешит блокировку .then, прежде чем утверждать, что success является правдой. Поскольку метод возвращает обещание, вы можете просто использовать: await service.getSettlement(parms, '0000000');, но для использования await вам нужно будет добавить async, поэтому описание it станет: it('should download a file and success should be true', async (() =>

bc1105 31.07.2018 19:48

Это изменило ошибку на: Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL, а затем Error: Expected no open requests, found 1: POST http://localhost:5000/api/settlement, который, как я предполагаю, взят из блока afterEach.

cjb110 01.08.2018 11:52

Вам необходимо подписаться на свой service.getSettlement (...), и в рамках этой подписки вы можете проверить свое ожидание (service.success) .toBeTruthy (). Как упоминалось в cjb100, вы проверяете свойство успеха до того, как будет сделан запрос.

Erbsenkoenig 04.03.2019 14:31
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
2
5
1 950
0

Другие вопросы по теме