Angular 使用 HttpClient 测试服务对我不起作用 [英] Angular Testing a service using HttpClient is not working for me

查看:24
本文介绍了Angular 使用 HttpClient 测试服务对我不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理一个 Angular 5 项目,没什么大不了的.虽然我从 2.1/2.2 早期就退出了 Angular2+ 业务.

I'm working on a Angular 5 Project, it's nothing serious. Though I've been out of the Angular2+ business since early 2.1/2.2.

所以我有这个调用公共 API 的服务,但是我的测试一直失败:错误:预期有一个匹配条件的请求匹配 URL:http://api.icndb.com/jokes/random/10",没有找到.

So I've got this Service which calls a public API, however my test keeps failing with: Error: Expected one matching request for criteria "Match URL: http://api.icndb.com/jokes/random/10", found none.

代码:

fact.service.spec.ts

fact.service.spec.ts

import {HttpClientTestingModule, HttpTestingController} from "@angular/common/http/testing";
import {TestBed, inject} from "@angular/core/testing";
import {FactService} from "./fact.service";
import {Fact} from "../models/fact";
import {FactHttpResponse} from "../models/factHttpResponse";

describe("FactService", () => {
    let factService: FactService;
    let httpMock: HttpTestingController;

    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [HttpClientTestingModule],
            providers: [FactService],
        });
        httpMock = TestBed.get(HttpTestingController);
        factService =  TestBed.get(FactService);
    });

    // TODO: Something is going wrong with this test get some help online
    it("Should be able to retrieve Facts in subscription when calling loadFacts", (done) => {
    const factList: Fact[] = [
        {id: 1, joke: "a"},
        {id: 2, joke: "a"},
    ];

    const factResponse: FactHttpResponse = { value: factList};

    factService.subscribe(val => {
        expect(val).toEqual(factList);
        done();
    });

    const mockRequest = httpMock
        .expectOne(factService.CHUCK_NORRIS_API.replace("{count}", "10"));
    expect(mockRequest.request.method).toEqual('GET');

    factService.loadFacts();

    mockRequest.flush(factResponse);
});

afterEach(inject([HttpTestingController], (httpMock: HttpTestingController) => {
    httpMock.verify();
}));
});

fact.service.ts

fact.service.ts

 import { HttpClient } from "@angular/common/http";
 import { Injectable } from "@angular/core";
 import { Subject } from "rxjs/Subject";

 import {Fact} from "../models/fact";
 import {FactHttpResponse} from "../models/factHttpResponse";

@Injectable()
export class FactService {

// public for testing purposes
public readonly CHUCK_NORRIS_API = "http://api.icndb.com/jokes/random/{count}";
private factSubject = new Subject();
private facts: Fact[] = [];
private favorites: Fact[] = [];

constructor(private http: HttpClient) { }

public subscribe(callback: (value: Fact[]) => void) {
    return this.factSubject.subscribe(callback);
}

public loadFacts(count = 10) {
    this.http.get<FactHttpResponse>(this.CHUCK_NORRIS_API.replace("{count}", count.toString()))
        .subscribe(data => {
           if (data.value) {
               this.facts = data.value
                   .map(f => {
                       f.favorite = !!this.favorites.find(fav => fav.id === f.id);
                       return f;
                   });
               this.factSubject.next(this.facts);
           }
        });
}
}

该代码确实有效,但我似乎无法对其进行测试:-(.如果我删除了 verifyOne,它实际上会抱怨对错误中提到的完全相同的 url 的打开请求.

The code actually works, but I can't seem to test it :-(. If I remove the verifyOne it actually complains about an open request to the exact same url mentioned in error.

推荐答案

由于是您的方法 factService.loadFacts() 生成了 HTTP 请求,因此您拥有测试的最后三个部分乱序.应该是(有评论):

Since it is your method factService.loadFacts() that is generating the HTTP request, you have the last three pieces of your test out of order. It should be (with comments):

describe(..., () => {
    it(..., () => {
        ...

        // queue up the http request in the mockHttp request queue
        factService.loadFacts();

        // verify that there is now one (and only one) request queued up
        const mockRequest = httpMock
            .expectOne(factService.CHUCK_NORRIS_API.replace("{count}", "10"));
        expect(mockRequest.request.method).toEqual('GET');

        // satisfy the pending request in the mockHttp request queue
        mockRequest.flush(factResponse);
    });

    // Bonus tip: you already have mockHttp in the describe() scope.  Simplify:
    afterEach(() => {
        // verify there are no unsatisfied requests in the mockHttp queue
        httpMock.verify();
    });
});

这篇关于Angular 使用 HttpClient 测试服务对我不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆