gpt4 book ai didi

javascript - 无法多次模拟函数 react 、测试

转载 作者:行者123 更新时间:2023-12-02 02:10:01 28 4
gpt4 key购买 nike

我想测试我的组件:

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);。 Jest 的反馈:

  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)

当然,第三个测试(基本渲染,获取错误)因此失败。

我不能使用 spyOn() 来代替,因为我的 fetcher 是一个没有对象的单独函数。

@@更新@@

有我的 fetcherreadData 函数:

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;
};

最佳答案

您必须为 readData 提供模拟实现也是如此。

根据 Jest 规范,

We can create a mock function with jest.fn(). If no implementation is given, the mock function will return undefined when invoked.


这将使您的测试更有意义。

 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();
});

@更新答案

Sorry to say that you can't achieve what you want. The reason is the render function is called only once in your test case so it means that the fetcher and readData API will call only once.

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();
});

即使你提供了mockResolvedValue,它也会再次给出 undefined因为渲染函数没有机会第二次调用 fetcher 的模拟版本和readData .

关于javascript - 无法多次模拟函数 react 、测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67845313/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com