我有以下组件。。。
export default class TextInput extends PureComponent<TextInputProps> {
private handleOnChange = (event: OnChangeEvent): void => {
if (!this.props.disabled && this.props.onChange) {
this.props.onChange(event)
}
}
private handleOnBlur = (event: OnBlurEvent): void => {
if (!this.props.disabled && this.props.onBlur) {
this.props.onBlur(event)
}
}
public render(): ReactNode {
return (
<Styled.TextInput
id={this.props.id}
type={this.props.type}
onChange={this.handleOnChange}
onBlur={this.handleOnBlur}
disabled={this.props.disabled}
/>
)
}
}
我正在尝试使用以下测试来测试handleOnChange函数。。。
const mockOnChange = jest.fn((): void => { })
const mockOnBlur = jest.fn((): void => { })
const minHandlerProps ={
id: 'test',
type: 'text',
onChange: mockOnChange,
onBlur: mockOnBlur,
}
describe('handleOnChange', () => {
it('Should not call the onChange prop when it's been passed and TextInput is disabled', () => {
const wrapper = shallow(<TextInput {...minHandlerProps} disabled={true} />)
const instance = wrapper.instance()
instance.handleOnChange()
expect(minHandlerProps.onChange).not.toHaveBeenCalled()
})
it('Should call the onChange prop when it's been passed and TextInput is not disabled', () => {
const wrapper = shallow(<TextInput {...minHandlerProps} />)
const instance = wrapper.instance()
instance.handleOnChange()
expect(minHandlerProps.onChange).toHaveBeenCalled()
})
})
测试按此顺序通过,但如果我围绕交换顺序,则不应调用onChange道具测试失败。
这是因为在这个例子中,onChange道具已经在第一个it((中被调用了吗?
我应该为此单独写一篇描述吗?
我已经在控制台上记录了道具的正确传递,看起来它们是正确的,所以我对这种行为感到不知所措。感谢任何能对此有所了解的人。
通过在描述块之外定义mock函数,您可以在所有测试之间共享每个函数的一个实例。这意味着您可以看到来自其他测试的调用,因此您的测试依赖于顺序(对于单元测试来说,这是一件非常糟糕的事情(。
对此有多种解决方案:
-
为每个测试创建一个新实例,例如在
beforeEach
:中describe('handleOnChange', () => { let minHandlerProps; let mockOnBlur; let mockOnChange; beforeEach(() => { mockOnChange = jest.fn((): void => { }) mockOnBlur = jest.fn((): void => { }) minHandlerProps = { id: 'test', type: 'text', onChange: mockOnChange, onBlur: mockOnBlur, } }); ... });
-
使用
mockClear
:在测试之间明确重置每个describe('handleOnChange', () => { beforeEach(() => { mockOnBlur.mockClear(); mockOnChange.mockClear(); }); ... });
-
使用
clearAllMocks
:在测试之间显式重置所有模拟describe('handleOnChange', () => { beforeEach(() => { jest.clearAllMocks(); }); ... });
-
通过在配置中将
clearMocks
设置为true
,让Jest重置测试之间的所有模拟。
顺便说一句,我不建议测试在实例上调用handleOnChange
是否会调用模拟函数prop。这就是实现-组件的行为是当Styled.TextInput
发生变化时调用回调,或者更好的是,当与该组件发生某些交互时调用回调。模拟这些事件会减少与当前实现的耦合。