对具有多个 HTTP 请求的函数进行单元测试

Unit test for a function with more than one HTTP request

我在为间接调用多个 HTTP 请求的函数编写单元测试时遇到问题。

正在测试的

Service结构如下:

/* content.service.ts */
import { Injectable } from "@angular/core"
import { ApiService } from "services/api/api.service"

@Injectable()
export class ContentService {
  public languages: Array<any>
  public categories: Array<any>

  constructor(private apiService: ApiService) {}

  public async fetchLanguages(): Promise<boolean> {
    const data: any = await this.apiService.getData("language")

    if (!data) return false

    this.languages = data
    return true
  }

  public async fetchCategories(): Promise<boolean> {
    const data: any = await this.apiService.getData("category")

    if (!data) return false

    this.categories = data
    return true
  }

  public async initService(): Promise<boolean> {
    const statusLanguages: boolean = await this.fetchLanguages()

    if (!statusLanguages) return false

    const statusCategories: boolean = await this.fetchCategories()

    if (!statusCategories) return false

    return true
  }
}

服务测试文件看起来像这样:

/* content.service.spec.ts */
import {
  HttpClientTestingModule,
  HttpTestingController
} from "@angular/common/http/testing"
import { TestBed } from "@angular/core/testing"

import { ApiService } from "services/api/api.service"
import { ContentService } from "./content.service"

describe("ContentService:", () => {
  let contentService: ContentService
  let httpMock: HttpTestingController

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [ HttpClientTestingModule ],
      providers: [ ApiService, ContentService ]
    })

    contentService = TestBed.get(ContentService)
    httpMock = TestBed.get(HttpTestingController)
  })

  afterEach(() => {
    httpMock.verify()
  })

  /* Dummy data */
  const languages = [
    { id: 1, uid: "en", active: true },
    { id: 2, uid: "es", active: false },
    { id: 3, uid: "hr", active: false }
  ]

  const categories = [
    { id: 1, uid: "default" },
    { id: 2, uid: "alternative" }
  ]

  describe("initService:", () => {
    it("successful response", (done: DoneFn) => {
      contentService.initService().then(result => {
        expect(result).toEqual(true)
        expect(contentService.languages).toEqual(languages)
        expect(contentService.categories).toEqual(categories)
        done()
      })

      const requests = httpMock.match(req => !!req.url.match(/api\/data/))

      expect(requests.length).toBe(2)

      requests[0].flush({ status: "ok", data: languages })
      requests[1].flush({ status: "ok", data: categories })
    })
  })
})

当 运行 单元测试 ng test 时抛出以下错误:

TypeError: Cannot read property 'flush' of undefined

TypeError 与行有关:

requests[1].flush({ status: "ok", data: categories })

这让我得出第一个请求得到正确处理的结论,而第二个请求则没有。

HttpTestingController 中的方法 match 不应该捕获所有与提供的正则表达式匹配的 HTTP 请求吗?

编写单元测试时,您应该只测试一个 unit。在这种情况下,您的单位是 ContentService。请记住,您不必测试它的依赖项。正如我所见,ApiService 是您服务中的一个依赖项,用于发出 Http 请求。所以你没有测试你是否正在发出 http 请求。您只需使用 模拟值 jasmine 间谍对象 .

模拟 ApiService
  const spy = jasmine.createSpyObj('ApiService', ['getData']);

  TestBed.configureTestingModule({
    providers: [
      ContentService,
      { provide: ApiService, useValue: spy }
    ]
  });

你必须在这里测试的是 ContentService 中的变量根据输入值获得正确的值和方法的 return 值。

您可以单独测试您的 ApiService。在进行单元测试时,不要尝试测试 类 的依赖关系。