简体   繁体   English

错误:如果 axios 提取在 React 组件 react-testing-library/msw 之外初始化,则连接 ECONNREFUSED 127.0.0.1:80

[英]Error: connect ECONNREFUSED 127.0.0.1:80 if an axios fetch gets initialized outside of a react component react-testing-library/msw

I'm getting the ECONNREFUSED error and it looks like my msw server isn't catching my get request when I start a get outside of a React component (which shaves some time off of the response).我收到 ECONNREFUSED 错误,当我在 React 组件之外启动 get 时,我的 msw 服务器似乎没有捕捉到我的 get 请求(这会缩短响应时间)。

When axios.get is uses inside of the useEffect everything works as normal and the msw picks up the request with no errors.当 axios.get 在 useEffect 内部使用时,一切正常,msw 无误地接收请求。 Is there a special way to setup react-testing-library with msw so that I can initialize an axios.get() outside of react components and then have the component pick up the promise once it's loaded.有没有一种特殊的方法可以使用 msw 设置 react-testing-library,这样我就可以在 react 组件之外初始化 axios.get() ,然后让组件在加载后获取 promise。

Thanks, get tool, but I just couldn't find how to get this working.谢谢,获取工具,但我找不到如何让它工作。

const signinPromise = axios.get(`signin?ajax=true`);

const Index = () => {
    useEffect(() => {
        (async () => {
            try {
                const response = await signinPromise;
                // ... do something with data etc
            } catch (err) {
            } finally {
            }
        })();
    }, []);

    return <>{/* content here */}</>;
};

test that's failing测试失败

import { screen } from '@testing-library/dom';
import { render, waitFor } from 'jestTestUtils';
import Index from './Index';

test('Signed in -> 404 page renders when given a bad route.', async () => {
    render(<Index />, { route: '/imabadroute' });

    await waitFor(() => expect(screen.getByRole('heading', { name: /chloë: add 404 page here to show nothing is at this route/i })));
});

My setup is as follows:我的设置如下:

server-handlers.ts服务器处理程序.ts

/**
 * these are the happy path responses for endpoints that we want to exist for tests so the pages load properly during tests
 */
import { rest } from 'msw';
import { getActivities, getAlertTypes, getDashboard, getSearch, getTab, getUserAccounts } from './data';

export const handlers = [
    rest.get('/signin', (req, res, ctx) => {
        return res(ctx.status(200), ctx.json(getUserAccounts({ amount: 2, overrides: [{ disabled: false }, { disabled: false }] })));
    }),
    rest.post('/signin', (req, res, ctx) => {
        return res(ctx.status(200), ctx.json(getUserAccounts({ amount: 2, overrides: [{ disabled: false }, { disabled: false }] })));
    }),
    rest.get(`/accounts/:accountId/tweet_event/types`, (req, res, ctx) => {
        return res(ctx.status(200), ctx.json(getAlertTypes()));
    }),
    rest.get(`/accounts/:accountId/event_dashboard`, (req, res, ctx) => {
        return res(ctx.status(200), ctx.json(getDashboard({ tabAmount: 1 })));
    }),
    rest.get(`/accounts/:accountId/event_dashboard/searches/:searchId`, (req, res, ctx) => {
        return res(ctx.status(200), ctx.json(getTab()));
    }),
    rest.get(`/accounts/:accountId/event_dashboard/searches/:searchId/search`, (req, res, ctx) => {
        return res(ctx.status(200), ctx.json(getSearch()));
    }),
    rest.get(`/accounts/:accountId/event_dashboard/searches/:searchId/activities`, (req, res, ctx) => {
        return res(ctx.status(200), ctx.json(getActivities({ amount: 2 })));
    }),
];

server.ts服务器.ts

/** this is just building a server with all the end points setup in server-handlers */
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import { handlers } from './server-handlers';

const server = setupServer(...handlers);
export { server, rest };

server-env.ts服务器-env.ts

/** our mock api is setup before each test, so the happy path is available to all tests */
import { server } from './server';

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

jestTestUtils.tsx jestTestUtils.tsx

import { CssBaseline, ThemeProvider } from '@mui/material';
import '@testing-library/jest-dom/extend-expect';
import { render, RenderOptions } from '@testing-library/react';
import { ReactElement } from 'react';
import { BrowserRouter } from 'react-router-dom';
import theme from '../theme';

interface RenderOptionsWithRoute extends RenderOptions {
    route: string;
}

interface Props {
    children: JSX.Element;
}

const AllTheProviders = ({ children }: Props) => (
    <ThemeProvider theme={theme}>
        <CssBaseline />
        <BrowserRouter>{children}</BrowserRouter>
    </ThemeProvider>
);

const customRender = (ui: ReactElement, options?: Omit<RenderOptionsWithRoute, 'wrapper'>) => {
    window.history.pushState({}, 'Test page', options?.route || '/');
    return render(ui, { wrapper: AllTheProviders, ...options });
};

export * from '@testing-library/react';
export { customRender as render };

jest.config.ts开玩笑.config.ts

export default {
    // Automatically clear mock calls, instances and results before every test
    clearMocks: true,

    // An array of glob patterns indicating a set of files for which coverage information should be collected
    collectCoverageFrom: ['./src/routes/**', './src/router/**', './src/utils/**'],

    // The directory where Jest should output its coverage files
    coverageDirectory: 'coverage',

    // An array of directory names to be searched recursively up from the requiring module's location
    moduleDirectories: [
        /** gives an absolute path to the root directory so jestTestUtils can be imported by an absolute path */
        'node_modules',
        'src/testing',
    ],

    /**
     * A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
     *
     * mirrors the resolve.alias object in webpack.config.js so the tests can import the same as in the code
     */
    moduleNameMapper: {
        '^@mui/styled-engine$': '@mui/styled-engine-sc',
        '^routes(.*)$': '<rootDir>/src/routes/$1',
        '^router(.*)$': '<rootDir>/src/router/$1',
        '^stores(.*)$': '<rootDir>/src/stores/$1',
        '^utils(.*)$': '<rootDir>/src/utils/$1',
        // svgr support
        '\\.svg': '<rootDir>/src/testing/__mocks__/svg.ts',
    },

    // A list of paths to modules that run some code to configure or set up the testing framework before each test
    setupFilesAfterEnv: ['<rootDir>/src/testing/__mocks__/setup-env.ts'],

    // The test environment that will be used for testing
    testEnvironment: 'jest-environment-jsdom',
};

My guess here is that since you're using msw and you're triggering the get request once you import the file, the server might still not be up to catch your request.我的猜测是,由于您使用的是msw并且在导入文件后触发了获取请求,因此服务器可能仍无法捕获您的请求。 In that case, I'll try using require or dynamic import to import the component within the specific test and it will work.在这种情况下,我将尝试使用require或动态导入在特定测试中导入组件,它会起作用。

Something like this:是这样的:

  it("should catch request", () => {
    const { App } = require("./App");
    render(<App />);
  });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM