首页 > 其他分享 >[Unit testing] Testing a fetch promise

[Unit testing] Testing a fetch promise

时间:2024-04-19 14:35:13浏览次数:21  
标签:fetchMock testing const resolve repos Testing api promise expect

Code:

import type { paths } from "@octokit/openapi-types";

type OrgRepoResponse =
  paths["/repos/{owner}/{repo}"]["get"]["responses"]["200"]["content"]["application/json"];

export type Fetch = typeof fetch;

export class GithubApi {
  constructor(
    private token: string | undefined,
    private fetch: Fetch = fetch,
    private delay: (ms: number) => Promise<void> = delay
  ) {}

  async getRepositories(user: string) {
    let page = 1;
    const repos: OrgRepoResponse[] = [];
    while (true) {
      const response = await this.fetch(
        `https://api.github.com/users/${user}/repos?per_page=30&page=${page}`,
        {
          headers: {
            "User-Agent": "Qwik Workshop",
            "X-GitHub-Api-Version": "2022-11-28",
          },
        }
      );
      const json = (await response.json()) as OrgRepoResponse[];
      repos.push(...json);
      if (json.length < 30) {
        break;
      }
      page++;
    }
    return repos;
  }

  async getRepository(user: string, repo: string) {
    const headers: HeadersInit = {
      "User-Agent": "Qwik Workshop",
      "X-GitHub-Api-Version": "2022-11-28",
    };
    if (this.token) {
      headers["Authorization"] = "Bearer " + this.token;
    }

    return Promise.race([
      this.delay(4000).then(() => {
        return { response: "timeout" };
      }),
      this.fetch(`https://api.github.com/repos/${user}/${repo}`, {
        headers,
      }).then((response) => {
        return response.json();
      }),
    ]);
  }
}

export function delay(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

 

Test:

import { describe, test, vi, beforeEach, Mock } from "vitest";
import { Fetch, GithubApi, delay } from "./api";

describe("github-api", () => {
  let fetchMock: Mock<Parameters<Fetch>, Promise<Response>>;
  let api: GithubApi;
  let delayMock: Mock<[number], Promise<void>>;

  beforeEach(() => {
    delayMock = vi.fn<[number], Promise<void>>(mockPromise);
    fetchMock = vi.fn<Parameters<Fetch>, Promise<Response>>(mockPromise);
    api = new GithubApi("TOKEN", fetchMock, delayMock);
  });

  describe("getRepository", () => {
    test("should return repository information", async ({ expect }) => {
      const responsePromise = api.getRepository("USERNAME", "REPO");

      expect(fetchMock).toHaveBeenCalledWith(
        "https://api.github.com/repos/USERNAME/REPO",
        {
          headers: {
            "User-Agent": "Qwik Workshop",
            "X-GitHub-Api-Version": "2022-11-28",
            Authorization: "Bearer TOKEN",
          },
        }
      );
      fetchMock.mock.results[0].value.resolve(new Response('"MockResponse"'));
      expect(await responsePromise).toEqual("MockResponse");
    });

    test("should timeout after x seconds with time out response", async ({
      expect,
    }) => {
      const responsePromise = api.getRepository("USERNAME", "REPO");

      expect(fetchMock).toHaveBeenCalledWith(
        "https://api.github.com/repos/USERNAME/REPO",
        {
          headers: {
            "User-Agent": "Qwik Workshop",
            "X-GitHub-Api-Version": "2022-11-28",
            Authorization: "Bearer TOKEN",
          },
        }
      );
      expect(delayMock).toHaveBeenCalledWith(4000);
      delayMock.mock.results[0].value.resolve();
      expect(await responsePromise).toEqual({ response: "timeout" });
    });
  });

  describe("getRepositories", () => {
    test("should fetch all repositories for a user", async ({ expect }) => {
      const responsePromise = api.getRepositories("USERNAME");
      expect(fetchMock).toHaveBeenCalledWith(
        "https://api.github.com/users/USERNAME/repos?per_page=30&page=1",
        expect.any(Object)
      );
      const repoSet1 = new Array(30).fill(null).map((_, i) => ({ id: i }));
      fetchMock.mock.results[0].value.resolve(
        new Response(JSON.stringify(repoSet1))
      );
      await delay(0);
      const repoSet2 = [{ id: 30 }];
      fetchMock.mock.results[1].value.resolve(
        new Response(JSON.stringify(repoSet2))
      );
      expect(await responsePromise).toEqual([...repoSet1, ...repoSet2]);
    });
  });
});

function mockPromise<T>(): Promise<T> & {
  resolve: typeof resolve;
  reject: typeof reject;
} {
  let resolve!: (value: T) => void;
  let reject!: (error: any) => void;
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  }) as any;
  promise.resolve = resolve;
  promise.reject = reject;
  return promise;
}

 

标签:fetchMock,testing,const,resolve,repos,Testing,api,promise,expect
From: https://www.cnblogs.com/Answer1215/p/18145822

相关文章

  • [Testing adn BDD] Introduction to Test and Behavior Driven Development
    TheImportanceofTestingThevalueoftesting"Ifit'sworthbuilding,it'sworthtesting.Ifit;snotworthtesting,whyareyouwastingyourtimetoworkngonit?"--ScottAmbler,agiledate.orgDesignprinciplesforApolloUsea......
  • promise实现
    //定义状态常量constPENDING='pending',FULFILLED='fulfilled',REJECTE='reject'functionMyPromise(executor){constself=this//缓存promise对象//初始执行状态为pendingself.status=PENDING//成功回调self.onResolveCb......
  • GRPC - Load testing Production-Grade APIs
      https://ghz.sh/  ......
  • GRPC - Unit testing Production-Grade APIs
      ......
  • Promise 内置的方法有哪些
    在JavaScript中,Promise对象有几个内置的方法:Promise.resolve(value):返回一个解析过的Promise对象,该对象的状态和值分别由value决定。Promise.reject(reason):返回一个拒绝的Promise对象,该对象的状态和原因分别由reason决定。Promise.all(iterable):接收一个可迭代......
  • 小程序 Api promise 化
      工具-构建npm-miniprogram_npm下出现miniprogram-api-promise即可正常使用 使用方法:如果提示没有找到miniprogram-api-promise,可以清除缓存重新编译试一下  ......
  • Javascript Promise用法详解
    1、约定本文的demo代码有些是伪代码,不可以直接执行。没有特殊说明,本文所有demo都是基于ES6规范。Object.method代表是静态方法,Object#method代表的是实例方法。如Promise#then代表的是Promise的实例方法,Promise.resolve代表的是Promise的静态方法.2、什么......
  • 通俗讲解promise
      JavaScript中的Promise是一种特殊的对象,它用于解决异步编程中的复杂性问题,特别是回调的问题。我们可以把它比喻成现实生活中的一个“承诺”:想象一下,你正在等待朋友帮你做一件事情(比如买一杯咖啡),但你不确定他们何时能完成。这时,你可以向朋友要一个“承诺”,即一个保证:......
  • Promises/A+ 详解及实现
    规范:Promises/A+https://promisesaplus.com/此篇文章将在Node环境通过 Class 语法来实现一个符合Promises/A+规范的 MyPromise ,通过官方872个测试用例文章中x.x.x标记如2.1.1表示规范中对应的规范序号;myPromise 表示 MyPromise 的一个实例对象【2.......
  • Java登陆第四十一天——Promise、async关键字、await关键字
    在学习axios之前,需要学习ES6提供的Promise对象。普通函数和回调函数学习Promise的预备知识,回调函数普通函数普通函数:正常调用的函数,普通函数执行完毕后才会继续执行下一行代码。按照编码顺序执行。functionf1(){console.log("普通函数f1执行");}functionf2(......