axios在componentDidMount中获取数据后如何拍摄jest snapshot?
Posted
技术标签:
【中文标题】axios在componentDidMount中获取数据后如何拍摄jest snapshot?【英文标题】:How to take a jest snapshot after axios fetched data in componentDidMount? 【发布时间】:2019-05-01 22:06:41 【问题描述】:要测试的组件
class Carousel extends React.Component
state =
slides: null
componentDidMount = () =>
axios.get("https://s3.amazonaws.com/rainfo/slider/data.json").then(res =>
this.setState( slides: res.data )
)
render()
if (!slides)
return null
return (
<div className="slick-carousel">
... markup trancated for bravity
</div>
)
export default Carousel
测试
import React from "react"
import renderer from "react-test-renderer"
import axios from "axios"
import Carousel from "./Carousel"
const slides = [
ID: "114",
REFERENCE_DATE: "2018-07-02",
...
,
ID: "112",
REFERENCE_DATE: "2018-07-06",
...
,
...
]
jest.mock("axios")
it("", () =>
axios.get.mockImplementationOnce(() => Promise.resolve( data: slides ))
const tree = renderer.create(<Carousel />).toJSON()
expect(tree).toMatchSnapshot()
)
快照只记录null
,因为在执行的那一刻我猜想state.slides = null
。
在 axios 完成获取数据后,我无法确定如何运行期望。
大多数在线示例要么使用酶,要么显示带有返回承诺的异步函数的测试。我找不到一个只使用 jest 和渲染组件来显示示例的示例。
我尝试制作测试函数async
,也使用done
回调,但没有运气。
【问题讨论】:
【参考方案1】:简而言之:
it("", async () =>
axios.get.mockImplementationOnce(() => Promise.resolve( data: slides ))
const tree = renderer.create(<Carousel />);
await Promise.resolve();
expect(tree.toJSON()).toMatchSnapshot()
)
应该做的工作
详细说明:除了您已经模拟了对 API 数据的调用之外,它仍然以异步方式进行。所以我们需要toMatchSnapshot
调用到微任务队列的末尾。 setTimeout(..., 0)
或 setImmediate
也可以,但我发现 await Promise.resolve()
更容易识别为“下面的所有内容都即将结束”
[UPD] 修复 sn-p: .toJSON
必须在等待之后,它返回的对象永远不会被更新
【讨论】:
感谢您的帮助和良好的解释。我能够想出 `Promise.resolve(renderer.create(shallow
而不是渲染器,这是否也有效?
@Zheng-rongCai 如果它是浅层渲染并且 XHR 调用应该发生在一些嵌套的孩子中......那将不会被渲染,因为它是浅层渲染 - 不是,它不会工作。但否则它应该工作【参考方案2】:
接受的答案第二天开始失败。经过一些调整,这似乎工作:
import React from "react"
import renderer from "react-test-renderer"
import axios from "axios"
import Carousel from "./Carousel"
jest.mock("axios")
const slides = sampleApiResponse()
const mockedAxiosGet = new Promise(() => ( data: slides ))
axios.get.mockImplementation(() => mockedAxiosGet)
// eventhough axios.get was mocked, data still comes anychrnonously,
// so during first pass state.slides will remain null
it("returns null initally", () =>
const tree = renderer.create(<Carousel />).toJSON()
expect(tree).toMatchSnapshot()
)
it("uses fetched data to render carousel", () =>
const tree = renderer.create(<Carousel />)
mockedAxiosGet.then(() =>
expect(tree.toJSON()).toMatchSnapshot()
)
)
function sampleApiResponse()
return [
ID: "114",
REFERENCE_DATE: "2018-07-02",
...
,
ID: "114",
REFERENCE_DATE: "2018-07-02",
...
,
]
【讨论】:
promisenew Promise(() => ( data: slides ))
永远不会得到解决。你需要Promise.resolve()
工厂方法。使用构造函数 new Promise()
您需要将解析器作为参数并像 new Promise(resolver => resolver( data: slides ))
一样调用它,但 Promise.resolve()
的作用完全相同,同时具有更好的可读性以上是关于axios在componentDidMount中获取数据后如何拍摄jest snapshot?的主要内容,如果未能解决你的问题,请参考以下文章
async/await 不适用于 ComponentDidMount 中的 react.js
如何在多个文件中分解 REACTJS 中的 Axios 调用?
Axios.get 返回纯 html 而不是 JSON 返回数据
为啥在 componentDidMount 中取消异步/ajax 请求