RTK Query测试错误与MSW和vitest

huangapple go评论76阅读模式
英文:

RTK Query Testing Error with MSW and vitest

问题

I'm trying to test a component in React that uses RTK Query + MSW + Vitest. It works fine on the browser but while testing RTK Query with vitest it throws this error:

{ status: 'FETCH_ERROR', error: 'TypeError: fetch failed' }

I've setup a public repo with the configuration i'm using to replicate the error.

Another error RTK Query throws only while testing is:

TypeError: Failed to parse URL from /api/test?page=1&limit=10

This happens when i setup the fetchBaseQuery - baseUrl as empty or as a relative URL. I have to specify 'http://localhost...' or it wont work. But, it works in the browser.

Repo with the error

Followed some articles on the matter with no success
Searched Stackoverflow and found
Searched RTK query repo issues and found a similar issue but with jest instead of vitest
I've tried clearing query cache between tests - no success.

App.jsx

import { useTestQuery } from "./services/test";

export const App = () => {
  const { data } = useTestQuery({ page: 1, limit: 10 });
  console.log(data);
  return (
    <>
      <h1>{data ? data.data.map((i) => i) : "loading"}</h1>
    </>
  );
};

redux/index.js

import { configureStore } from "@reduxjs/toolkit";
import { setupListeners } from "@reduxjs/toolkit/query";
import { testApi } from "../services/test";

const store = configureStore({
  reducer: {
    [testApi.reducerPath]: testApi.reducer,
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat([testApi.middleware]),
});
setupListeners(store.dispatch);

export default store;

services/apiSetup.js

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

export const emptyApi = createApi({
  baseQuery: fetchBaseQuery({
    baseUrl: "http://localhost:3000"
  }),
  tagTypes: ["test"],
  endpoints: () => ({}),
});

services/test.js

import { emptyApi } from "./apiSetup";

export const testApi = emptyApi.injectEndpoints({
  endpoints: (build) => ({
    test: build.query({
      query: ({ page = 1, limit = 10 }) => {
        return { url: `test?page=${page}&limit=${limit}` };
      },
      providesTags: ["test"],
      transformErrorResponse: (result) => console.log(result),
    }),
  }),
  overrideExisting: false,
});

export const { useTestQuery, usePrefetch } =
  testApi;

mocks/server.js

import { setupServer } from 'msw/node';
import { handlers } from './handlers';

export const server = setupServer(...handlers);

mocks/handler.js

import { test } from "./handlers/test";

export const handlers = [...test];

mocks/handlers/test.js

import { rest } from "msw";

function randomIntFromInterval(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min);
  }

export const test = [
  rest.get("http://localhost:3000/test", (req, res, ctx) => {
    console.log(req)
    return res(
      ctx.delay(randomIntFromInterval(100, 1000)),
      ctx.status(200),
      ctx.json({ data: [1, 2, 3, 4, 5], total: 5 })
    );
  }),
];

testSetup.js

import { expect, afterEach, vi } from "vitest";
import { server } from "../mocks/server";
import { cleanup } from "@testing-library/react";
import matchers from "@testing-library/jest-dom";

// extends Vitest's expect method with methods from react-testing-library
expect.extend(matchers);


beforeAll(() => server.listen({ onUnhandledRequest: "bypass", cors: true }));

afterEach(() => {
  server.resetHandlers();
  cleanup();
});

afterAll(() => server.close());

App.test.jsx

import React from "react";
import { describe, expect, test } from "vitest";
import { render, screen } from "@testing-library/react";
import { Provider } from "react-redux";
import store from "../../redux";
import App from "./";

const wrapper = (children) => {
  return <Provider store={store}>{children}</Provider>;
};

function setup(jsx) {
  return {
    ...render(wrapper(jsx)),
  };
}

describe("App test", () => {
  test("Should test", async () => {
    setup(<App />);
    await screen.findByText(/12345/);
    screen.debug(undefined, 50000);
  });
});
英文:

I'm trying to test a component in React that uses RTK Query + MSW + Vitest. It works fine on the browser but while testing RTK Query with vitest it throws this error:

{ status: &#39;FETCH_ERROR&#39;, error: &#39;TypeError: fetch failed&#39; }

I've setup a public repo with the configuration i'm using to replicate the error.

Another error RTK Query throws only while testing is:

TypeError: Failed to parse URL from /api/test?page=1&amp;limit=10

This happens when i setup the fetchBaseQuery - baseUrl as empty or as a relative URL. I have to specify 'http://localhost...' or it wont work. But, it works in the browser.

Repo with the error

Followed some articles on the matter with no success
Searched Stackoverflow and found
Searched RTK query repo issues and found a similar issue but with jest instead of vitest
I've tried clearing query cache between tests - no success.

App.jsx

import { useTestQuery } from &quot;./services/test&quot;;

export const App = () =&gt; {
  const { data } = useTestQuery({ page: 1, limit: 10 });
  console.log(data);
  return (
    &lt;&gt;
      &lt;h1&gt;{data ? data.data.map((i) =&gt; i) : &quot;loading&quot;}&lt;/h1&gt;
    &lt;/&gt;
  );
};

redux/index.js

import { configureStore } from &quot;@reduxjs/toolkit&quot;;
import { setupListeners } from &quot;@reduxjs/toolkit/query&quot;;
import { testApi } from &quot;../services/test&quot;;

const store = configureStore({
  reducer: {
    [testApi.reducerPath]: testApi.reducer,
  },
  middleware: (getDefaultMiddleware) =&gt;
    getDefaultMiddleware().concat([testApi.middleware]),
});
setupListeners(store.dispatch);

export default store;

services/apiSetup.js

import { createApi, fetchBaseQuery } from &quot;@reduxjs/toolkit/query/react&quot;;

export const emptyApi = createApi({
  baseQuery: fetchBaseQuery({
    baseUrl:&quot;http://localhost:3000&quot;
  }),
  tagTypes: [&quot;test&quot;],
  endpoints: () =&gt; ({}),
});

services/test.js

import { emptyApi } from &quot;./apiSetup&quot;;

export const testApi = emptyApi.injectEndpoints({
  endpoints: (build) =&gt; ({
    test: build.query({
      query: ({ page = 1, limit = 10 }) =&gt; {
        return { url: `test?page=${page}&amp;limit=${limit}` };
      },
      providesTags: [&quot;test&quot;],
      transformErrorResponse: (result) =&gt; console.log(result),
    }),
  }),
  overrideExisting: false,
});

export const { useTestQuery,usePrefetch } =
  testApi;

mocks/server.js

import { setupServer } from &#39;msw/node&#39;;
import { handlers } from &#39;./handlers&#39;;

export const server = setupServer(...handlers);

mocks/handler.js

import { test } from &quot;./handlers/test&quot;;

export const handlers = [...test];

mocks/handlers/test.js

import { rest } from &quot;msw&quot;;

function randomIntFromInterval(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min);
  }

export const test = [
  rest.get(&quot;http://localhost:3000/test&quot;, (req, res, ctx) =&gt; {
    console.log(req)
    return res(
      ctx.delay(randomIntFromInterval(100, 1000)),
      ctx.status(200),
      ctx.json({ data: [1, 2, 3, 4, 5], total: 5 })
    );
  }),
];

testSetup.js

import { expect, afterEach, vi } from &quot;vitest&quot;;
import { server } from &quot;../mocks/server&quot;;
import { cleanup } from &quot;@testing-library/react&quot;;
import matchers from &quot;@testing-library/jest-dom&quot;;

// extends Vitest&#39;s expect method with methods from react-testing-library
expect.extend(matchers);


beforeAll(() =&gt; server.listen({ onUnhandledRequest: &quot;bypass&quot;, cors: true }));

afterEach(() =&gt; {
  server.resetHandlers();
  cleanup();
});

afterAll(() =&gt; server.close());

App.test.jsx

import React from &quot;react&quot;;
import { describe, expect, test } from &quot;vitest&quot;;
import { render, screen } from &quot;@testing-library/react&quot;;
import { Provider } from &quot;react-redux&quot;;
import store from &quot;../../redux&quot;;
import App from &quot;./&quot;;

const wrapper = (children) =&gt; {
  return &lt;Provider store={store}&gt;{children}&lt;/Provider&gt;;
};

function setup(jsx) {
  return {
    ...render(wrapper(jsx)),
  };
}

describe(&quot;App test&quot;, () =&gt; {
  test(&quot;Should test&quot;, async () =&gt; {
    setup(&lt;App /&gt;);
    await screen.findByText(/12345/);
    screen.debug(undefined, 50000);
  });
});

答案1

得分: 1

尝试安装 msw 1.1.0,在发布 https://github.com/mswjs/msw/pull/1545 后,似乎一切与您的设置正常运行。

英文:

Try to install msw 1.1.0, after release https://github.com/mswjs/msw/pull/1545 everything seems to work fine with your setup.

答案2

得分: 1

如果在使用RTK Query、MSW和vitest进行测试时出现FETCH_ERROR,则很可能需要在设置函数中定义fetch,类似于以下方式:https://github.com/reduxjs/redux-toolkit/blob/67a69e876812282ad7fe5590d173a88bd7b80282/packages/toolkit/jest.setup.js

//@ts-ignore
const nodeFetch = require('node-fetch')
//@ts-ignore
global.fetch = nodeFetch
//@ts-ignore
global.Request = nodeFetch.Request
英文:

If you get FETCH_ERROR in your tests with RTK Query, MSW, vitest, then most likely you'll need to define fetch in a setup function, similar to: https://github.com/reduxjs/redux-toolkit/blob/67a69e876812282ad7fe5590d173a88bd7b80282/packages/toolkit/jest.setup.js

//@ts-ignore
const nodeFetch = require(&#39;node-fetch&#39;)
//@ts-ignore
global.fetch = nodeFetch
//@ts-ignore
global.Request = nodeFetch.Request

huangapple
  • 本文由 发表于 2023年1月9日 19:05:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75056364.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定