不能用不同的unittest来模拟react hook的返回值



下面的组件:

import { VFC } from 'react';
import { useParams } from 'react-router-dom';
export const MyComponent: VFC = () => {
const { sourceTemplate } = useParams();
return (
<div>
<p>
<b>{sourceTemplate}</b>
</p>
</div>
);
};

下面是我的测试类:

import { render } from '@testing-library/react';
import { MyComponent } from './MyComponent';
const mockFn = jest.fn();
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => mockFn
}));
describe('MyComponent', () => {
it('First test', async () => {
mockFn.mockReturnValue({ sourceTemplate: 'hello' });
render(<MyComponent />);
})
});

我希望看到"hello"显示在我的组件,但我得到未定义。理想情况下,我希望有不同的测试与不同的模拟返回值,因此mockFn,理想情况下,我可以为每个测试设置不同的返回值。

下面的代码可以正常工作,但是对于多个测试来说配置性较差。

import { render } from '@testing-library/react';
import { MyComponent } from './MyComponent';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => ({ sourceTemplate: 'hello' })
}));
describe('MyComponent', () => {
it('First test', async () => {
render(<MyComponent />);
})
});

我怎么能有一个单一的模拟函数,我在每个测试中为react钩子useParams返回不同的值?

这两个示例测试是不同的:

第一个:

const mockFn = jest.fn();
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => mockFn
}));

您说useParams返回一个函数(mockFn),因此为了使其工作,useParams应该像useParams()一样被调用,而事实并非如此。

关于第二个:

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => ({ sourceTemplate: 'hello' })
}));

你说useParams返回一个对象,这就是它工作的原因。

设置useParams: mockFn可能会抛出ReferenceError: Cannot access 'mockFn' before initialization错误。

所以,这里最好的方法是模拟返回值:
import { render, screen } from "@testing-library/react";
let mockReturn = "";
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useParams: () => ({ sourceTemplate: mockReturn }),
}));
describe("MyComponent", () => {
beforeEach(() => {
mockReturn = "";
});
it("First test", async () => {
mockReturn = "c";
render(<App />);
screen.debug();
});
});

如果你检查你的代码,你会注意到在第一个代码片段中你使用了

useParams: () => mockFn

而在第二个

useParams: () => ({ sourceTemplate: 'hello' })

因此,在第一个代码片段中,将useParams设置为返回mockFn函数的函数,而在第二个代码片段中将其设置为返回所需对象的函数。


第一个代码片段应该是useParams: () => mockFn()(注意函数名后面的())。或者干脆做useParams: mockFn就更好了。

最新更新