问题
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.
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.
code:
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
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);
}
});
}
}
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.
回答1:
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();
});
});
来源:https://stackoverflow.com/questions/47517629/angular-testing-a-service-using-httpclient-is-not-working-for-me