进入功能组件+挂钩和React Unit测试,我正在尝试执行以下操作:
在一个组件中,我使用了实用程序API文件中的函数。在挂载时,我对我的api进行了异步函数调用。 在该实用程序API文件中,我想以各种方式模拟该函数,因此当我在测试中渲染组件时,它将在挂钩中看到不同的响应。它将返回一个Promise,该Promise将根据我正在测试的内容解析为不同的值。
所以我不是在嘲笑第三方模块,而是在嘲笑我自己的模块。
/**
* App.js
*/
import React, { useState, useEffect } from 'react'
import { getData } from './api'
export default function App() {
const [data, setData] = useState()
// get data from api on mount
useEffect(() => {
loadData()
}, [])
// get the data and set the "data" state variable
const loadData = async () => {
try {
let d = await getData() // <---- this is what i want to mock with different values per test
setData(d)
} catch (err) {
setErr('Error occurred')
}
}
render (
<div>
data is: {JSON.stringify(data)}
</div>
)
}
只是在寻找一种在每次测试的测试文件中定义模拟的方法,因此在渲染组件时,它将解析/拒绝为不同的值
答案 0 :(得分:2)
您可以按照以下步骤从api中模拟getData函数:
select distinct [date], id
from #test
order by [date] desc
select [date],
count(*) over (order by date desc rows between current row and 7 following ) count_7_day,
count(*) over (order by date desc rows between current row and 30 following ) count_30_day
from (select distinct [date], id
from #test )x
order by [date] desc
这基本上是在导入api时返回模拟工厂返回的字典。
您可以使用import {render, wait} from 'react-testing-library';
import {getData} from 'path/to/api';
jest.mock('path/to/api', () => ({
getData: jest.fn()
}))
it('succeeds when promise resolves', () => {
// This overrides getData with a resolved promise
getData.mockResolvedValue('foo');
const { container } = render(<App />);
// You need to wait for your mock promise to resolve
return wait(() => {
expect(container.textContent).toBe('data is: "foo"');
});
});
it('fails when promise rejects', () => {
// This overrides getData with a rejected promise
getData.mockRejectedValue('oh no');
const { container } = render(<App />);
return wait(() => {
expect(container.textContent).toBe('Error occurred');
});
});
模拟该模块,然后覆盖该函数以在每次测试中解析/拒绝为不同的值。
答案 1 :(得分:1)
Daniel的答案说明了一种模拟模块的好方法。模拟getData
的另一种方法是依赖注入。
import {getData} from './api';
export default function App(props) {
const [data, setData] = useState()
// get data from api on mount
useEffect(() => {
loadData()
}, [])
// get the data and set the "data" state variable
const loadData = async () => {
try {
let d = await props.getData() // <-- change this to props.getData()
setData(d)
} catch (err) {
setErr('Error occurred')
}
}
}
App.defaultProps = { getData };
通过将“真实” getData
设置为默认道具,当您不使用道具渲染<App />
时,您的应用将从'./api'调用“真实” getData。
但是,在测试中,您现在可以传递模拟getData
:
it('succeeds when promise resolves', () => {
const mockGetData = jest.fn().mockResolvedValue('foo');
const { container } = render(<App getData={mockGetData} />);
// You need to wait for your mock promise to resolve
return wait(() => {
expect(container.textContent).toBe('data is: "foo"');
});
});
it('fails when promise rejects', () => {
const mockGetData = jest.fn().mockRejectedValue('oh no');
const { container } = render(<App getData={mockGetData} />);
return wait(() => {
expect(container.textContent).toBe('Error occurred');
});
});