使用 useState 和 setTimeout 测试组件
Test a component with useState and setTimeout
代码结构如下:
FunctionComponent.js
...
const [open, handler] = useState(false);
setTimeout(() => {handler(true);}, 2000);
...
return (
...
<div className={active ? 'open' : 'close'}>
)
comp.test.js
jest.useFakeTimers();
test('test case 1', () => {
expect(wrapper.find('open').length).toBe(0);
jest.advanceTimersByTime(2000);
<b>expect(wrapper.find('open').length).toBe(1);</b>
jest.useRealTimers();
});
问题是测试中粗体写的表达式表示open class的长度仍然是0,所以实际和预期不符。
您想测试钩子的结果而不是钩子本身,因为这就像测试 React。您实际上想要一个测试,检查打开的 class 是否存在然后不存在(反之亦然),看起来您正在尝试。
简而言之,要解决您的问题,您需要在选择 class 时使用 ".open"
。我还建议使用 .exists()
检查 class 而不是 ".length()"
然后你也可以使用 ".toBeTruthy()"
。
您也可以考虑改进以 Jest/Enzyme combined 格式编写测试:
import { shallow } from 'enzyme';
import { FunctionComponent } from './FunctionComponent.jsx';
jest.useFakeTimers();
describe('<FunctionCompnent />', () => {
const mockProps = { prop1: mockProp1, prop2: mockProp2, funcProp3: jest.fn() };
const wrapper = shallow(<FunctionComponent {...mockProps} />);
afterEach(() => {
jest.advanceTimersByTime(2000);
});
afterAll(() => {
jest.useRealTimers();
});
it('should render as closed initially', () => {
expect(wrapper.find('.close').exists()).toBeTruthy();
// you could also add the check for falsy of open if you wanted
// expect(wrapper.find('.open').exists()).toBeFalsy();
});
it('should change to open after 2 seconds (or more)', () => {
expect(wrapper.find('.open').exists()).toBeTruthy();
// you could also add the check for falsy of close if you wanted
// expect(wrapper.find('.close').exists()).toBeFalsy();
});
});
编辑:抱歉,我再次检查你的代码后发现我把测试写反了,现在应该修复了。
代码结构如下:
FunctionComponent.js
...
const [open, handler] = useState(false);
setTimeout(() => {handler(true);}, 2000);
...
return (
...
<div className={active ? 'open' : 'close'}>
)
comp.test.js
jest.useFakeTimers();
test('test case 1', () => {
expect(wrapper.find('open').length).toBe(0);
jest.advanceTimersByTime(2000);
<b>expect(wrapper.find('open').length).toBe(1);</b>
jest.useRealTimers();
});
问题是测试中粗体写的表达式表示open class的长度仍然是0,所以实际和预期不符。
您想测试钩子的结果而不是钩子本身,因为这就像测试 React。您实际上想要一个测试,检查打开的 class 是否存在然后不存在(反之亦然),看起来您正在尝试。
简而言之,要解决您的问题,您需要在选择 class 时使用 ".open"
。我还建议使用 .exists()
检查 class 而不是 ".length()"
然后你也可以使用 ".toBeTruthy()"
。
您也可以考虑改进以 Jest/Enzyme combined 格式编写测试:
import { shallow } from 'enzyme';
import { FunctionComponent } from './FunctionComponent.jsx';
jest.useFakeTimers();
describe('<FunctionCompnent />', () => {
const mockProps = { prop1: mockProp1, prop2: mockProp2, funcProp3: jest.fn() };
const wrapper = shallow(<FunctionComponent {...mockProps} />);
afterEach(() => {
jest.advanceTimersByTime(2000);
});
afterAll(() => {
jest.useRealTimers();
});
it('should render as closed initially', () => {
expect(wrapper.find('.close').exists()).toBeTruthy();
// you could also add the check for falsy of open if you wanted
// expect(wrapper.find('.open').exists()).toBeFalsy();
});
it('should change to open after 2 seconds (or more)', () => {
expect(wrapper.find('.open').exists()).toBeTruthy();
// you could also add the check for falsy of close if you wanted
// expect(wrapper.find('.close').exists()).toBeFalsy();
});
});
编辑:抱歉,我再次检查你的代码后发现我把测试写反了,现在应该修复了。