英文:
How to test a React Suspense 'promise wrapper' in Jest, when fetching data via axios
问题
以下是你要翻译的代码部分:
我正在尝试更新我的 useAxios 钩子,以使其与 React Suspense 一起工作,遵循此指南:
https://deadsimplechat.com/blog/react-suspense/
const promiseWrapper = (promise: Promise<any>) => {
let status = 'pending';
let result: any;
const suspender = promise.then(
(value: any) => {
status = 'success';
result = value;
},
(error: any) => {
status = 'error';
result = error;
}
);
return () => {
switch (status) {
case 'pending':
throw suspender;
case 'success':
return result.data;
case 'error':
throw result;
default:
throw new Error('Unknown status');
}
};
};
export const useAxios = <T>(requestConfig: AxiosRequestConfig): T | null => {
const [response, setResponse] = useState(null);
useEffect(() => {
const doRequest = () => {
const result = axios.request(requestConfig);
setResponse(promiseWrapper(result));
};
doRequest(requestConfig);
}, []);
return response;
};
这是你的代码的翻译部分,不包括问题或其他内容。如果需要进一步的帮助,请随时提出。
英文:
I'm trying to update my useAxios hook to work with React Suspense, following this guide:
https://deadsimplechat.com/blog/react-suspense/
const promiseWrapper = (promise: Promise<any>) => {
let status = 'pending';
let result: any;
const suspender = promise.then(
(value: any) => {
status = 'success';
result = value;
},
(error: any) => {
status = 'error';
result = error;
}
);
return () => {
switch (status) {
case 'pending':
throw suspender;
case 'success':
return result.data;
case 'error':
throw result;
default:
throw new Error('Unknown status');
}
};
};
export const useAxios = <T,>(requestConfig: AxiosRequestConfig): T | null => {
const [response, setResponse] = useState(null);
useEffect(() => {
const doRequest = () => {
const result = axios.request(requestConfig);
setResponse(promiseWrapper(result));
};
doRequest(requestConfig);
}, []);
return response;
};
This 'promiseWrapper' pattern seems to be pretty common when using Suspense in react, with async calls.
I'm still wrapping my head around this, but here's my understanding of how it works...
We wrap our promise (the axios API call) in the promise wrapper, and then when the hook returns, it is returning the switch function that will return either return the data on success, throw the promise itself if its pending, and throws an error if there's an exception.
This all seems to work fine when I run the application, but I'm trying to write jest unit tests for when the useAxios hook returns an 'error' or is 'pending' and I cant get it to work.
For the error scenario, I have this jest test:
it('should call endpoint and throw error on exception', async () => {
mockedAxios.request.mockRejectedValueOnce(new Error('error'));
expect(() => {
renderHook(() => useAxios<TestResponseType>({}))
}).toThrowError();
});
But the error is never thrown. And I'm not sure how to mock the pending response at all.
Any pointers on how I can get these test cases passing?
答案1
得分: 1
以下是您要翻译的内容:
Test the custom hook with a dumb component, the <Suspense/>
component and a <ErrorBoundary/>
component.
E.g.
import { ErrorBoundary } from "react-error-boundary";
import { useAxios } from "./useAxios";
import { render, screen } from "@testing-library/react";
import '@testing-library/jest-dom';
import axios from "axios";
import React, { Suspense } from "react";
describe('76404248', () => {
test('should pass', async () => {
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => { })
const requestSpy = jest.spyOn(axios, 'request').mockRejectedValueOnce(new Error('test error'))
const TestComp = () => {
useAxios({})
return null;
}
render(
<ErrorBoundary
fallbackRender={({ error }) => <p>{error.message}</p>}
>
<Suspense fallback={<p>loading</p>}>
<TestComp />
</Suspense>
</ErrorBoundary>
)
expect(await screen.findByText(/test error/i)).toBeInTheDocument();
screen.debug();
errorSpy.mockRestore();
requestSpy.mockRestore();
})
})
Test result:
PASS stackoverflow/76404248/useAxios.test.tsx (17.177 s)
76404248
✓ should pass (165 ms)
console.log
<body>
<div>
<p>
test error
</p>
</div>
</body>
at logDOM (node_modules/@testing-library/dom/dist/pretty-dom.js:82:13)
-------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------|---------|----------|---------|---------|-------------------
All files | 83.33 | 50 | 85.71 | 82.61 |
useAxios.ts | 83.33 | 50 | 85.71 | 82.61 | 10-11,24,28
-------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 18.565 s, estimated 23 s
package versions:
"@testing-library/react": "^11.2.7",
"react-error-boundary": "^4.0.9",
"react": "^16.14.0",
英文:
Test the custom hook with a dumb component, the <Suspense/>
component and a <ErrorBoundary/>
component.
E.g.
import { ErrorBoundary } from "react-error-boundary";
import { useAxios } from "./useAxios";
import { render, screen } from "@testing-library/react";
import '@testing-library/jest-dom';
import axios from "axios";
import React, { Suspense } from "react";
describe('76404248', () => {
test('should pass', async () => {
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => { })
const requestSpy = jest.spyOn(axios, 'request').mockRejectedValueOnce(new Error('test error'))
const TestComp = () => {
useAxios({})
return null;
}
render(
<ErrorBoundary
fallbackRender={({ error }) => <p>{error.message}</p>}
>
<Suspense fallback={<p>loading</p>}>
<TestComp />
</Suspense>
</ErrorBoundary>
)
expect(await screen.findByText(/test error/i)).toBeInTheDocument();
screen.debug();
errorSpy.mockRestore();
requestSpy.mockRestore();
})
})
Test result:
PASS stackoverflow/76404248/useAxios.test.tsx (17.177 s)
76404248
✓ should pass (165 ms)
console.log
<body>
<div>
<p>
test error
</p>
</div>
</body>
at logDOM (node_modules/@testing-library/dom/dist/pretty-dom.js:82:13)
-------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------|---------|----------|---------|---------|-------------------
All files | 83.33 | 50 | 85.71 | 82.61 |
useAxios.ts | 83.33 | 50 | 85.71 | 82.61 | 10-11,24,28
-------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 18.565 s, estimated 23 s
package versions:
"@testing-library/react": "^11.2.7",
"react-error-boundary": "^4.0.9",
"react": "^16.14.0",
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论