如何在 Angular 中测试 JSONP HTTP 请求?
Posted
技术标签:
【中文标题】如何在 Angular 中测试 JSONP HTTP 请求?【英文标题】:How do I test a JSONP HTTP request in Angular? 【发布时间】:2018-05-22 01:56:21 【问题描述】:我正在使用HttpClientModule 和HttpClientJsonpModule 在服务中发出 JSONP HTTP 请求。
app.module.ts
import BrowserModule from '@angular/platform-browser';
import NgModule from '@angular/core';
import HttpClientModule, HttpClientJsonpModule from '@angular/common/http';
import AppComponent from './app.component';
@NgModule(
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule,
HttpClientJsonpModule
],
providers: [],
bootstrap: [AppComponent]
)
export class AppModule
此服务使用 HttpClient class 中的 jsonp 方法从指定 URL 获取 JSONP 响应。我认为这个响应被JsonpInterceptor截获并发送到处理请求的JsonpClientBackend。
example.service.ts
import Injectable from '@angular/core';
import HttpClient from '@angular/common/http';
@Injectable()
export class ExampleService
url = "https://archive.org/index.php?output=json&callback=callback";
constructor(private http: HttpClient)
getData()
return this.http.jsonp(this.url, 'callback');
使用HttpClientTestingModule,我注入HttpTestingController,这样我就可以模拟和刷新我的JSONP HTTP 请求。
example.service.spec.ts
import TestBed, inject from '@angular/core/testing';
import
HttpClientTestingModule,
HttpTestingController
from '@angular/common/http/testing';
import ExampleService from './example.service';
describe('ExampleService', () =>
let service: ExampleService;
let httpMock: HttpTestingController;
beforeEach(() =>
TestBed.configureTestingModule(
imports: [HttpClientTestingModule],
providers: [ExampleService]
);
service = TestBed.get(ExampleService);
httpMock = TestBed.get(HttpTestingController);
);
describe('#getData', () =>
it('should return an Observable<any>', () =>
const dummyData = id: 1 ;
service.getData().subscribe(data =>
expect(data).toEqual(dummyData);
);
const req = httpMock.expectOne(service.url); // Error
expect(req.request.method).toBe('JSONP');
req.flush(dummyData);
);
);
);
最后,我得到了错误
Error: Expected one matching request for criteria "Match URL: https://archive.org/index.php?output=json&callback=callback", found none.
如果我将请求方法更改为 GET,此测试将按预期工作。
据我所知,HttpClientTestingModule 使用了 HttpClientTestingBackend 但没有 JsonpClientTestingBackend 或相应的拦截器。
【问题讨论】:
JSONP 不是在幕后的 GET 请求(以及其他属性)吗? 根据文档,我相信jsonp方法被JsonpInterceptor拦截,将其转移到JsonpClientBackend。 【参考方案1】:根据 Angular 开发人员的说法,这是a bug。现在有一个解决方法。
example.service.spec.ts
import TestBed, inject from '@angular/core/testing';
// Import the HttpClientJsonpModule, HttpBackend, and JsonpClientBackend
import HttpClientJsonpModule, HttpBackend, JsonpClientBackend from '@angular/common/http';
import HttpClientTestingModule, HttpTestingController from '@angular/common/http/testing';
import ExampleService from './example.service';
describe('ExampleService', () =>
let service: ExampleService;
let httpMock: HttpTestingController;
beforeEach(() =>
TestBed.configureTestingModule(
imports: [HttpClientTestingModule],
// Use the HttpBackend instead of the JsonpClientBackend
providers: [ExampleService, provide: JsonpClientBackend, useExisting: HttpBackend ]
);
service = TestBed.get(ExampleService);
httpMock = TestBed.get(HttpTestingController);
);
describe('#getData', () =>
it('should return an Observable<any>', () =>
const dummyData = id: 1 ;
service.getData().subscribe(data =>
expect(data).toEqual(dummyData);
);
// Pass a function to the expectOne method
const req = httpMock.expectOne(request => request.url === service.url);
expect(req.request.method).toBe('JSONP');
req.flush(dummyData);
);
);
);
【讨论】:
以上是关于如何在 Angular 中测试 JSONP HTTP 请求?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Angular 和 Jsonp 中使用 HERE Geocoder Autocomplete API?