如何在 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&amp;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?

如何将 jsonp 与 angular-ui 日历一起使用

Angular 12 Httpclient jsonp - 如何传递自定义回调参数?

在 Angular JS 1.6 中处理 JSONP 响应

JSONP 请求在 Angular 应用程序中给出 404

JSONP http请求在Angular中给出404