javascript - 如何在 Angular 中测试 JSONP HTTP 请求?

标签 javascript angular unit-testing http jsonp

我正在使用 HttpClientModuleHttpClientJsonpModule在服务中发出 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 { }

此服务使用 jsonp来自 HttpClient class 的方法从指定的 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 , 我注入(inject) 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);
    });
  });
});

最后,我得到了错误

错误:预期有一个符合条件“匹配 URL:https://archive.org/index.php?output=json&callback=callback”的匹配请求,但没有找到。

如果我将请求方法更改为 GET,此测试将按预期工作。

据我所知,HttpClientTestingModule 使用 HttpClientTestingBackend,但没有 JsonpClientTestingBackend 或相应的拦截器。

如何在 Angular 中测试 JSONP HTTP 请求?

最佳答案

根据 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);
    });
  });
});

关于javascript - 如何在 Angular 中测试 JSONP HTTP 请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47703877/

相关文章:

javascript - 如何使用 Google Drive 的 api 打开文件?

angular - 将 ngFor 与异步管道一起使用以显示可观察数组

javascript - 使用 Angular 2 的 Oauth 2 弹出窗口

unit-testing - 无法从仅 jvm 模块访问 commonMain 多平台类

java - Maven 单元测试 FileNotFound 错误

javascript - jQuery Find() 和 XML 在 IE 中不起作用

javascript - 触发事件和调度事件有什么区别?

javascript - 如何暂停页面上所有播放的音频

arrays - 将两个对象数组与 Angular 2 和 TypeScript 合并?

angularjs - 为什么在我的测试中所有 $document 函数都未定义?