测试自定义挂钩 usePrevious 时设置函数 returns 未定义
setup function returns undefined when testing a custom hook usePrevious
我从互联网上的某个地方获得了 usePrevious 挂钩的代码。 usePrevious 的代码如下所示:
export const usePrevious = (value) => {
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
};
现在,我正在学习测试与笑话和酶的反应。因此,我尝试测试 usePrevious 并遇到了一些问题。这是我的测试用例:
import React from 'react';
import { render } from 'enzyme';
import { usePrevious } from './customHooks';
const Component = ({ children, value }) => children(usePrevious(value));
const setup = (value) => {
let returnVal = '';
render(
<Component value={value}>
{
(val) => {
returnVal = val;
return null;
}
}
</Component>,
);
return returnVal;
};
describe('usePrevious', () => {
it('returns something', () => {
const test1 = setup('test');
const test2 = setup(test1);
expect(test2).toBe('test');
});
});
测试执行完成后,出现此错误:
Expected: 'test', Received: undefined
任何人都可以告诉我为什么我会变得不确定,这是在 React 中测试自定义钩子的正确方法吗?
根据@Dmitrii G 的评论建议,我更改了代码以重新渲染组件(之前我正在重新安装组件)。
这是更新后的代码:
import React from 'react';
import PropTypes from 'prop-types';
import { shallow } from 'enzyme';
import { usePrevious } from './customHooks';
const Component = ({ value }) => {
const hookResult = usePrevious(value);
return (
<div>
<span>{hookResult}</span>
<span>{value}</span>
</div>
);
};
Component.propTypes = {
value: PropTypes.string,
};
Component.defaultProps = {
value: '',
};
describe('usePrevious', () => {
it('returns something', () => {
const wrapper = shallow(<Component value="test" />);
console.log('>>>>> first time', wrapper.find('div').childAt(1).text());
expect(wrapper.find('div').childAt(0).text()).toBe('');
// Test second render and effect
wrapper.setProps({ value: 'test2' });
console.log('>>>>> second time', wrapper.find('div').childAt(1).text());
expect(wrapper.find('div').childAt(0).text()).toBe('test');
});
});
但我仍然遇到同样的错误
Expected: "test", Received: ""
引入 settimeout 时测试通过:
import React from 'react';
import PropTypes from 'prop-types';
import { shallow } from 'enzyme';
import { usePrevious } from './customHooks';
const Component = ({ value }) => {
const hookResult = usePrevious(value);
return <span>{hookResult}</span>;
};
Component.propTypes = {
value: PropTypes.string,
};
Component.defaultProps = {
value: '',
};
describe('usePrevious', () => {
it('returns empty string when component is rendered first time', () => {
const wrapper = shallow(<Component value="test" />);
setTimeout(() => {
expect(wrapper.find('span').text()).toBe('');
}, 0);
});
it('returns previous value when component is re-rendered', () => {
const wrapper = shallow(<Component value="test" />);
wrapper.setProps({ value: 'test2' });
setTimeout(() => {
expect(wrapper.find('span').text()).toBe('test');
}, 0);
});
});
我不太喜欢使用settimeout,所以我觉得我可能做错了。如果有人知道不使用 settimeout 的解决方案,请随时在此处 post。谢谢。
Enzyme by the hood 使用 React 的浅层渲染器。它有 issue with running effects。不确定它是否会很快修复。
setTimeout
的解决方法令我感到惊讶,不知道它是否有效。不幸的是,这不是通用方法,因为您需要在案例重新呈现的任何更改上使用它。真的很脆弱。
您可以使用 mount()
作为解决方案。
你也可以模拟浅层渲染 mount()
模拟每个嵌套组件:
jest.mock("../MySomeComponent.jsx", () =>
(props) => <span {...props}></span>
);
我从互联网上的某个地方获得了 usePrevious 挂钩的代码。 usePrevious 的代码如下所示:
export const usePrevious = (value) => {
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
};
现在,我正在学习测试与笑话和酶的反应。因此,我尝试测试 usePrevious 并遇到了一些问题。这是我的测试用例:
import React from 'react';
import { render } from 'enzyme';
import { usePrevious } from './customHooks';
const Component = ({ children, value }) => children(usePrevious(value));
const setup = (value) => {
let returnVal = '';
render(
<Component value={value}>
{
(val) => {
returnVal = val;
return null;
}
}
</Component>,
);
return returnVal;
};
describe('usePrevious', () => {
it('returns something', () => {
const test1 = setup('test');
const test2 = setup(test1);
expect(test2).toBe('test');
});
});
测试执行完成后,出现此错误:
Expected: 'test', Received: undefined
任何人都可以告诉我为什么我会变得不确定,这是在 React 中测试自定义钩子的正确方法吗?
根据@Dmitrii G 的评论建议,我更改了代码以重新渲染组件(之前我正在重新安装组件)。
这是更新后的代码:
import React from 'react';
import PropTypes from 'prop-types';
import { shallow } from 'enzyme';
import { usePrevious } from './customHooks';
const Component = ({ value }) => {
const hookResult = usePrevious(value);
return (
<div>
<span>{hookResult}</span>
<span>{value}</span>
</div>
);
};
Component.propTypes = {
value: PropTypes.string,
};
Component.defaultProps = {
value: '',
};
describe('usePrevious', () => {
it('returns something', () => {
const wrapper = shallow(<Component value="test" />);
console.log('>>>>> first time', wrapper.find('div').childAt(1).text());
expect(wrapper.find('div').childAt(0).text()).toBe('');
// Test second render and effect
wrapper.setProps({ value: 'test2' });
console.log('>>>>> second time', wrapper.find('div').childAt(1).text());
expect(wrapper.find('div').childAt(0).text()).toBe('test');
});
});
但我仍然遇到同样的错误
Expected: "test", Received: ""
引入 settimeout 时测试通过:
import React from 'react';
import PropTypes from 'prop-types';
import { shallow } from 'enzyme';
import { usePrevious } from './customHooks';
const Component = ({ value }) => {
const hookResult = usePrevious(value);
return <span>{hookResult}</span>;
};
Component.propTypes = {
value: PropTypes.string,
};
Component.defaultProps = {
value: '',
};
describe('usePrevious', () => {
it('returns empty string when component is rendered first time', () => {
const wrapper = shallow(<Component value="test" />);
setTimeout(() => {
expect(wrapper.find('span').text()).toBe('');
}, 0);
});
it('returns previous value when component is re-rendered', () => {
const wrapper = shallow(<Component value="test" />);
wrapper.setProps({ value: 'test2' });
setTimeout(() => {
expect(wrapper.find('span').text()).toBe('test');
}, 0);
});
});
我不太喜欢使用settimeout,所以我觉得我可能做错了。如果有人知道不使用 settimeout 的解决方案,请随时在此处 post。谢谢。
Enzyme by the hood 使用 React 的浅层渲染器。它有 issue with running effects。不确定它是否会很快修复。
setTimeout
的解决方法令我感到惊讶,不知道它是否有效。不幸的是,这不是通用方法,因为您需要在案例重新呈现的任何更改上使用它。真的很脆弱。
您可以使用 mount()
作为解决方案。
你也可以模拟浅层渲染 mount()
模拟每个嵌套组件:
jest.mock("../MySomeComponent.jsx", () =>
(props) => <span {...props}></span>
);