首页 > 解决方案 > 使用 Angular 6 HttpTestingController 对服务进行单元测试

问题描述

我有一个 Angular v6 服务,它调用一个 .net 核心 API 并接收一个 PDF 格式的 blob。当它从 API 接收到 OK 响应时,该服务还将一个标志设置为 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.log(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'
        });
    }));

标签: angulartypescriptunit-testinghttpjasmine

解决方案


推荐阅读