Gio*_*gio 9 unit-testing fetch reactjs jestjs react-testing-library
我想测试一个使用全局fetch方法的小型 React Web 应用程序。
fetch我尝试以这种方式嘲笑:
global.fetch = jest.spyOn(global, 'fetch').mockImplementation(endpoint =>
Promise.resolve({
json: () => Promise.resolve(mockResponse)
})
);
Run Code Online (Sandbox Code Playgroud)
...但是模拟似乎被忽略,而内置fetch似乎被使用:Error: connect ECONNREFUSED 127.0.0.1:80 ...看起来像是对内置的失败调用fetch。
然后我尝试使用jest.fn而不是jest.spyOn:
global.fetch = jest.fn(endpoint =>
Promise.resolve({
json: () => Promise.resolve(mockResponse)
})
);
Run Code Online (Sandbox Code Playgroud)
...并惊讶地发现了不同的错误。现在似乎已经考虑了模拟,但同时无法正常工作:
TypeError: Cannot read property 'then' of undefined
8 | this.updateTypes = this.props.updateTypes;
9 | this.updateTimeline = this.props.updateTimeline;
> 10 | fetch('/timeline/tags')
| ^
11 | .then(res => res.json())
12 | .then(tags => tags.map(tag => <option value={tag} key={tag} />))
13 | .then(options => options.sort((a, b) => a.key.localeCompare(b.key)))
Run Code Online (Sandbox Code Playgroud)
老实说,我发现 Jest 和 React 测试库的文档有点令人困惑。我正在做的事情可能存在什么问题?
我试图测试的 React 组件称为“App”,是使用 Create React App 生成的,并更改为包含对fetch. 我很乐意提供该组件的代码,但我相信问题出在测试中。
在我的文件的开头App.test.js,我import React from 'react';,然后import { render, fireEvent, waitFor, screen } from '@testing-library/react';,最后import App from './App';。随后,我尝试fetch以我描述的方式之一进行模拟,然后声明以下测试:
TypeError: Cannot read property 'then' of undefined
8 | this.updateTypes = this.props.updateTypes;
9 | this.updateTimeline = this.props.updateTimeline;
> 10 | fetch('/timeline/tags')
| ^
11 | .then(res => res.json())
12 | .then(tags => tags.map(tag => <option value={tag} key={tag} />))
13 | .then(options => options.sort((a, b) => a.key.localeCompare(b.key)))
Run Code Online (Sandbox Code Playgroud)
最后,我以global.fetch.mockRestore();.
Est*_*ask 19
存在ECONNREFUSED错误而不是fetch is not defined意味着fetch已被填充。它不是 JSDOM 的一部分,也不是由 Jest 本身填充的,而是特定于当前设置的。在本例中,polyfill 由 create-react-app 提供。
最好使用模拟现有的全局函数,jest.spyOn而不是将它们分配为global属性,这允许 Jest 进行清理。global.fetch = jest.spyOn(global, 'fetch')永远不应该做这样的事情,因为这会阻止fetch恢复。这可以解释TypeError: Cannot read property 'then' of undefined看似正确模拟的函数的错误。
模拟全局变量的正确且安全的方法是在每次测试之前模拟它们并在每次测试后恢复:
beforeEach(() => {
jest.spyOn(global, 'fetch').mockResolvedValue({
json: jest.fn().mockResolvedValue(mockResponse)
})
});
afterEach(() => {
jest.restoreAllMocks();
});
Run Code Online (Sandbox Code Playgroud)
global.fetch为了使模拟正常工作,不应该进行其他修改。
恢复模拟和间谍的更好方法是使用配置选项,因为jest.restoreAllMocks不这样做可能会导致意外的测试交叉污染,这是永远不希望的。
TypeError: Cannot read property 'then' of undefined出现错误的另一个原因是 Jest 错误地指向了fetchline,而错误实际上指向了另一行。如果源映射无法正常工作,就会发生这种情况。如果fetch正确模拟并且同一组件中还有其他then组件,那么这是对该错误的合理解释。
| 归档时间: |
|
| 查看次数: |
36077 次 |
| 最近记录: |