简体   繁体   English

AbortController 在 React 测试中不工作(开玩笑)

[英]AbortController not working in React test (Jest)

We have a function in our React project to fetch a list of stores.我们的 React 项目中有一个 function 来获取商店列表。 If the fetch takes longer than 3 seconds (set low for testing purposes) we abort the request and show an error.如果获取时间超过 3 秒(出于测试目的设置为低),我们将中止请求并显示错误。

const controller = new AbortController();
const getTimeout = setTimeout(() => controller.abort(), 3000);

const fetchStores = storeId => (
    ourFetchStoresFunction(`http://my-api/${storeId}`, {
        headers: { 'x-block': 'local-stores' },
        signal: controller.signal
    })
    .then((results) => {
        clearTimeout(getTimeout);
        return results
    })
    .catch((err) => { throw err; })
);

I am trying to trigger the Abort error from Jest.我正在尝试从 Jest 触发 Abort 错误。 I am using Mock Service Worker to intercept fetch requests and mock a delayed response:我正在使用 Mock Service Worker 拦截获取请求并模拟延迟响应:

import * as StoresAPI from '../Stores-api';
import { rest } from 'msw';
import { setupServer } from 'msw/node';

const server = setupServer(rest.get(`http://my-api/*`, (req, res, ctx) => {
    console.log('TEST');
    return res(
        ctx.delay(5000),
        ctx.status(200),
        ctx.json({ stores: ['hi']})
    )
}));

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

it('fetchStores should return a stores array', async () => {
    await StoresAPI.fetchStores(MOCK_STORES)
    .then((stores) => {
        expect(Array.isArray(stores)).toBe(true);
     })
    .catch();
});

When I run this, the delay works, it takes 5000 seconds for the mocked response to fire and the test to pass.当我运行它时,延迟起作用了,模拟的火灾响应和测试通过需要 5000 秒。 But...The test passes and it seems abortController is never called.但是...测试通过了,似乎从未调用过 abortController。 WHy is this happening?为什么会这样? And is there a better way to test this (ideally without using MSW or other library)?有没有更好的方法来测试它(最好不使用 MSW 或其他库)?

Your test is running synchronously;您的测试正在同步运行; Jest runs all the code, which includes firing off a Promise but not awaiting it, and then finishes. Jest 运行所有代码,包括触发 Promise 但不等待它,然后结束。 After the test finishes, the Promise returns, but no one is waiting for it.测试结束后,Promise 返回,但没有人等待。

The code in the .then block is never even reached by Jest, since it is not awaited. Jest 甚至都不会到达.then块中的代码,因为它没有被等待。

You can use async code inside Jest tests.您可以在 Jest 测试中使用async代码。 I suspect this may give your more mileage:我怀疑这可能会给你更多的里程:

// mock a quick response for this test
it('returns stores', async () => {
  const stores = await StoresAPI.fetchStores(MOCK_STORES)
  expect(stores).toEqual([/* returned array */])
})

// mock a long response for this test
it('times out', async () => {
  await expect(() => StoresAPI.fetchStores(MOCK_STORES)).rejects.toThrow();
})

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

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