如何在反应中使用 API 调用测试组件?
Posted
技术标签:
【中文标题】如何在反应中使用 API 调用测试组件?【英文标题】:How to test component with API call in react? 【发布时间】:2020-09-19 20:54:49 【问题描述】:我在测试从 API 获取数据并在屏幕上呈现的反应组件时遇到问题。 这是我得到的错误。
● Company Details › renders company details with given data
expect(received).toMatch(expected)
Expected substring: "Google"
Received string: "no name provided"
18 | );
19 |
> 20 | expect(getByTestId('company-name').textContent).toMatch('Google');
| ^
21 | expect(getByTestId('sponsors-visa').textContent).toMatch('Yes');
22 | expect(getByTestId('description').textContent).toMatch('this is a company description');
23 | );
at Object.<anonymous> (src/tests/components/company-detail/CompanyDetail.test.js:20:53)
我的测试文件CompanyDetail.test.js
代码:
import React from 'react';
import CompanyDetail from '../../../components/company-detail/CompanyDetail';
import BrowserRouter from 'react-router-dom';
import render from '@testing-library/react';
describe('Company Details', () =>
let mockData;
beforeEach(() =>
mockData = match: params: id: 4 ;
jest.mock('../../../components/effects/use-fetch.effect');
);
it('renders company details with given data', async () =>
const getByTestId = render(
<BrowserRouter>
<CompanyDetail ...mockData />,
</BrowserRouter>
);
expect(getByTestId('company-name').textContent).toMatch('Google');
expect(getByTestId('sponsors-visa').textContent).toMatch('Yes');
expect(getByTestId('description').textContent).toMatch('this is a company description');
);
);
我要测试的代码 (CompanyDetail.js
)
import CONSTANTS from '../../constants/constants';
import Link from 'react-router-dom';
import useFetch from '../effects/use-fetch.effect';
const CompanyDetail = (props) =>
const id = props.match.params;
const name, description, jobs, known_to_sponsor_visa = useFetch(`$CONSTANTS.BASE_URL/companies/$id`);
return (
<React.Fragment>
<Container>
<Row className="m-2">
<Col>
<Card>
<Card.Body>
<Card.Title>
<h3 data-testid="company-name">name ? name : 'no name provided'</h3>
</Card.Title>
<Card.Text data-testid="sponsors-visa">
<b>Known to sponsor work visa: </b>
known_to_sponsor_visa ? known_to_sponsor_visa : 'No data'
</Card.Text>
<Card.Text data-test-id="description">description</Card.Text>
</Card.Body>
</Card>
</Col>
</Row>
</Container>
</React.Fragment>
);
;
export default CompanyDetail;
以防万一需要use-fetch.effect.js
:
import useState, useEffect from 'react';
const useFetch = (url) =>
const [dataArray, setData] = useState([]);
useEffect(() =>
try
const fetchData = async () =>
const res = await fetch(url);
const dataArray = await res.json();
setData(dataArray.data)
fetchData();
catch (err)
console.error(err);
, [url]);
return dataArray;
;
export default useFetch;
我可以通过 props 发送数据来测试它,但我不知道如何模拟数据来测试该 url 以接收 id 并将其呈现到特定位置。任何帮助,将不胜感激。我知道为什么会出现错误,因为我没有通过任何公司名称作为 Google 进行检查。问题是我如何通过传递一些虚拟数据来测试它。
【问题讨论】:
这能回答你的问题吗? React - how do I unit test an API call in Jest? 【参考方案1】:由于useFetch
预计会以任何方式异步,这可能会影响组件的工作方式,因此它需要以比返回值的 Jest spy 更复杂的方式进行模拟。请求本身可以被模拟而不是整个useFetch
:
let data = name: 'Google', ... ;
spyOn(global, 'fetch').mockResolvedValue( json: jest.fn().mockResolvedValue( data ) );
...
expect(getByTestId('company-name').textContent).toMatch('no name provided');
await waitFor(() => expect(getByTestId('company-name').textContent).toMatch('Google'));
【讨论】:
你好@Estus,谢谢你的帮助。实施后我收到此错误。TypeError: Cannot destructure property 'name' of '(0 , _useFetch.default)(...)' as it is undefined.
我更新了代码,响应应该有data
属性。如果您没有删除jest.mock
,请考虑这样做,它也可能导致此错误。
它解决了我上面提到的问题。是的,我也删除了 jest.mock
并将 waitFor
更改为 waitForElement
。我从这一行 await waitFor(() => expect(getByTestId('company-name').textContent).toMatch('Google'));
收到我在问题上发布的错误。 Here 是我的要点。你能告诉我我哪里做错了吗?
我明白了。 waitFor 和 waitForElement 是不同的函数。 waitForElement 需要一个选择器,它不应该在这里工作,它也被弃用了。
当我在@testing-library
挖掘node_modules 时有wait-for-element.js
。每当我使用 waitFor
时,它都会显示错误:TypeError: (0 , _react2.waitFor) is not a function
。要使其与 waitForElement
一起使用,我必须进行哪些更改?以上是关于如何在反应中使用 API 调用测试组件?的主要内容,如果未能解决你的问题,请参考以下文章