我想测试我的组件:
const Courses: React.FC = () => {
const { data, error } = useSWR(
'some url...',
fetcher
);
console.log(data, error);
if (error) {
return (
<CoursesContainer>
<Error>Something went wrong.</Error>
</CoursesContainer>
);
}
if (!data) return <Loader title="loader" />;
return (
<CoursesContainer>
<CollapsibleTable courses={data} />
</CoursesContainer>
);
};
export default Courses;
但我不知道为什么我不能模拟它为每个测试返回不同的值。我试过了:
jest.mock('../../utils/fetcher', () => ({
fetcher: jest
.fn()
.mockReturnValue('default')
.mockReturnValueOnce('first call')
.mockReturnValueOnce('second call'),
readData: jest.fn(),
}));
test('Basic render. fetch pending', async () => {
const component = render(<Courses />);
await waitFor(() => component.findByTitle('loader'));
expect(component.baseElement).toMatchSnapshot();
});
test('Basic render, fetch success', async () => {
const component = render(<Courses />);
await waitFor(() => component.findByText('CollapsibleTable'));
expect(component.baseElement).toMatchSnapshot();
});
test('Basic render, fetch error', async () => {
const component = render(<Courses />);
await waitFor(() => component.findByText('Something went wrong.'));
expect(component.baseElement).toMatchSnapshot();
});
而且效果不佳。对于每个测试,只有 first call
console.log() - Courses.tsx 中的 console.log(data, error);
。
来自玩笑的反馈:
console.log
undefined undefined
at Courses (src/components/Courses.tsx:14:11)
console.log
first call undefined
at Courses (src/components/Courses.tsx:14:11)
console.log
first call undefined
at Courses (src/components/Courses.tsx:14:11)
console.log
first call undefined
at Courses (src/components/Courses.tsx:14:11)
当然,第三个测试 (Basic render, fetch error
) 是失败的原因。
我不能改用 spyOn()
,我的 fetcher
的 cos 是没有对象的单独函数。
@@更新@@
有我的 fetcher
和 readData
函数:
const fetcher = (url: string) => {
return fetch(url)
.then((response) => response.json())
.then((data: Array<IFetchData>) => readData(data));
};
const readData = (data: Array<IFetchData>) => {
let myData: Array<ICourse> = [];
[ there are some simple operations which create new myData array with
properties which I need (there is not any async operations)]
return myData;
};
答案 0 :(得分:2)
您还必须为 readData
提供模拟实现。
根据 jest 规范,
<块引用>我们可以用 jest.fn() 创建一个模拟函数。如果未给出实现,则模拟函数在调用时将返回 undefined。
这将使您的测试更有意义。
await waitForElementToBeRemoved(() => component.getByTitle('loader'));
我们正在等待加载器标题被删除,以确保标题首先显示,现在在加载器完成时将其删除。
jest.mock('../../utils/fetcher', () => ({
fetcher: jest
.fn()
.mockResolvedValue('default')
.mockResolvedValueOnce('first call')
.mockResolvedValueOnce('second call'),
readData: jest.fn().mockResolvedValue('Read call'), //provide reseolve value
//jest.fn() returns undefined when we dont't provide implementation
}));
test('Basic render. fetch pending', async () => {
const component = render(<Courses />);
await waitForElementToBeRemoved(() => component.getByTitle('loader'));
expect(component.baseElement).toMatchSnapshot();
});
test('Basic render, fetch success', async () => {
const component = render(<Courses />);
await waitForElementToBeRemoved(() => component.getByText('CollapsibleTable'));
expect(component.baseElement).toMatchSnapshot();
});
test('Basic render, fetch error', async () => {
const component = render(<Courses />);
await waitForElementToBeRemoved(() => component.getByText('Something went wrong.'));
expect(component.baseElement).toMatchSnapshot();
});
@更新的答案
<块引用> <块引用>很抱歉,您无法实现您想要的。原因是渲染函数在您的测试用例中仅被调用一次,因此这意味着 fetcher
和 readData
API 将仅调用一次。
const mockFn = jest.fn();
jest.mock('../../utils/fetcher', () => ({
fetcher: mockFn.mockResolvedValueOnce('first call'),
readData: mockFn.mockResolvedValue(['Read call']), // returns array
}));
test('Basic render. fetch pending', async () => {
const component = render(<Courses />);
await waitForElementToBeRemoved(() => component.getByTitle('loader'));
expect(mockFn).toHaveBeenCalledTimes(1); // test passed
expect(component.baseElement).toMatchSnapshot();
});
即使您再次提供 mockResolvedValueOnce,它也会给 undefined
,因为渲染函数没有机会第二次调用 fetcher
和 readData
的模拟版本。
答案 1 :(得分:1)
看起来您的 MockReturnValue 链出现故障。默认应该是最后,像这样:
jest.mock('../../utils/fetcher', () => ({
fetcher: jest
.fn()
.mockReturnValueOnce('first call')
.mockReturnValueOnce('second call')
.mockReturnValue('default'),
readData: jest.fn(),
}));
从这里查看批准的答案: Jest mock the same function twice with different arguments