React - 使用Jest和mock throws测试服务器请求的包装器:“错误:读取ECONNRESET”

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React - 使用Jest和mock throws测试服务器请求的包装器:“错误:读取ECONNRESET”相关的知识,希望对你有一定的参考价值。

TL; DR:我如何测试用React包装fetch的函数?

我正在用TypeScript构建一个React应用程序。要使用fetch api,我将这些库添加到我的tsconfig:

"lib": ["es2017", "dom"],

现在我写了以下函数:

import { Schema } from "normalizr";
import { camelizeAndNormalize } from "../../core";

export const getRequest = (fullUrlRoute: string, schema: Schema) =>
  fetch(fullUrlRoute).then(response =>
    response.json().then(json => {
      if (!response.ok) {
        return Promise.reject(json);
      }
      return Promise.resolve(camelizeAndNormalize(json, schema));
    })
  );

函数camelizeAndNormalize字面意思做它所说的。 (我正在使用normalizr规范我的Redux状态)。

现在我想用以下Jest测试来测试这个包装函数:

import fetch from "jest-fetch-mock";
import { schema } from "normalizr";
import { getRequest } from "./getRequests";

const response = {
  author: {
    id: "1",
    name: "Paul"
  },
  comments: [
    {
      commenter: {
        id: "2",
        name: "Nicole"
      },
      id: "324"
    }
  ],
  id: "123",
  title: "My awesome blog post"
};

const expected = {
  entities: {
    articles: {
      "123": {
        author: "1",
        comments: ["324"],
        id: "123",
        title: "My awesome blog post"
      }
    },
    comments: {
      "324": { id: "324", commenter: "2" }
    },
    users: {
      "1": { id: "1", name: "Paul" },
      "2": { id: "2", name: "Nicole" }
    }
  },
  result: "123"
};

const fullTestUrl = "https://google.com";

const user = new schema.Entity("users");
const comment = new schema.Entity("comments", {
  commenter: user
});
const testSchema = new schema.Entity("articles", {
  author: user,
  comments: [comment]
});

describe("get request", () => {
  beforeEach(() => {
    fetch.resetMocks();
  });

  it("calls the given fullUrlRoute and returns data", () => {
    fetch.mockResponseOnce(JSON.stringify(response));

    expect.assertions(3);

    return getRequest(fullTestUrl, testSchema).then(res => {
      expect(res).toEqual(expected);
      expect(fetch.mock.calls.length).toEqual(1);
      expect(fetch.mock.calls[0][0]).toEqual(fullTestUrl);
    });
  });

  it("recognizes when a response's status is not okay", () => {
    fetch.mockResponseOnce(JSON.stringify({ ok: false }), { status: 403 });

    expect.assertions(1);

    return getRequest(fullTestUrl, testSchema).catch(err => {
      expect(err.ok).toEqual(false);
    });
  });

  it("recognizes a failed fetch request", () => {
    fetch.mockReject(new Error("fake error message"));
    expect.assertions(1);

    return getRequest(fullTestUrl, testSchema).catch(err => {
      expect(err).toEqual(Error("fake error message"));
    });
  });
});

在这个测试中,我使用jest-fetch-mock模拟了fetch。此测试会抛出错误:

 FAIL  src/services/utils/serverRequests/GET/getRequests.test.ts
  ● Console

    console.error node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/virtual-console.js:29
      Error: Error: connect ECONNREFUSED 68.178.213.61:443
          at Object.dispatchError (/Users/jan/Startup/pontemio/pontem/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:65:19)
          at Request.client.on.err (/Users/jan/Startup/pontemio/pontem/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:676:20)
          at Request.emit (events.js:165:20)
          at Request.onRequestError (/Users/jan/Startup/pontemio/pontem/node_modules/request/request.js:881:8)
          at ClientRequest.emit (events.js:160:13)
          at TLSSocket.socketErrorListener (_http_client.js:389:9)
          at TLSSocket.emit (events.js:160:13)
          at emitErrorNT (internal/streams/destroy.js:64:8)
          at process._tickCallback (internal/process/next_tick.js:152:19) undefined
    console.error node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/virtual-console.js:29
      Error: Error: connect ECONNREFUSED 68.178.213.61:443
          at Object.dispatchError (/Users/jan/Startup/pontemio/pontem/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:65:19)
          at Request.client.on.err (/Users/jan/Startup/pontemio/pontem/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:676:20)
          at Request.emit (events.js:165:20)
          at Request.onRequestError (/Users/jan/Startup/pontemio/pontem/node_modules/request/request.js:881:8)
          at ClientRequest.emit (events.js:160:13)
          at TLSSocket.socketErrorListener (_http_client.js:389:9)
          at TLSSocket.emit (events.js:160:13)
          at emitErrorNT (internal/streams/destroy.js:64:8)
          at process._tickCallback (internal/process/next_tick.js:152:19) undefined
    console.error node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/virtual-console.js:29
      Error: Error: connect ECONNREFUSED 68.178.213.61:443
          at Object.dispatchError (/Users/jan/Startup/pontemio/pontem/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:65:19)
          at Request.client.on.err (/Users/jan/Startup/pontemio/pontem/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:676:20)
          at Request.emit (events.js:165:20)
          at Request.onRequestError (/Users/jan/Startup/pontemio/pontem/node_modules/request/request.js:881:8)
          at ClientRequest.emit (events.js:160:13)
          at TLSSocket.socketErrorListener (_http_client.js:389:9)
          at TLSSocket.emit (events.js:160:13)
          at emitErrorNT (internal/streams/destroy.js:64:8)
          at process._tickCallback (internal/process/next_tick.js:152:19) undefined

为什么模拟不起作用?如何测试在React with Jest中使用fetch的函数?

答案

找出我错过的东西。我需要将以下内容添加到我的src/setupTests.ts

// react-testing-library renders your components to document.body,
// this will ensure they're removed after each test.
// this adds jest-dom's custom assertions
import "jest-dom/extend-expect";
import "react-testing-library/cleanup-after-each";
// setupJest.js or similar file
const globalAny: any = global;
// tslint:disable-next-line
globalAny.fetch = require("jest-fetch-mock");

以上是关于React - 使用Jest和mock throws测试服务器请求的包装器:“错误:读取ECONNRESET”的主要内容,如果未能解决你的问题,请参考以下文章

[React Testing] Mock react-transition-group in React Component Tests with jest.mock

ThemeProvider 的 Jest Manual Mock

如何测试 Firebase 登录操作(React/Jest)

使用 Jest Mock Ajax

使用 React、Jest、Redux 和 Thunk 进行无限循环测试

使用 Jest 模拟 @apollo/react-hooks useQuery