为什么it函数的顺序在这个玩笑测试中很重要



我有以下组件。。。

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函数,您可以在所有测试之间共享每个函数的一个实例。这意味着您可以看到来自其他测试的调用,因此您的测试依赖于顺序(对于单元测试来说,这是一件非常糟糕的事情(。

对此有多种解决方案:

  1. 为每个测试创建一个新实例,例如在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,
    }
    });
    ...
    });
    
  2. 使用mockClear:在测试之间明确重置每个

    describe('handleOnChange', () => {       
    beforeEach(() => {
    mockOnBlur.mockClear();
    mockOnChange.mockClear();
    });
    ...
    });
    
  3. 使用clearAllMocks:在测试之间显式重置所有模拟

    describe('handleOnChange', () => {       
    beforeEach(() => {
    jest.clearAllMocks();
    });
    ...
    });
    
  4. 通过在配置中将clearMocks设置为true,让Jest重置测试之间的所有模拟。


顺便说一句,我不建议测试在实例上调用handleOnChange是否会调用模拟函数prop。这就是实现-组件的行为是当Styled.TextInput发生变化时调用回调,或者更好的是,当与该组件发生某些交互时调用回调。模拟这些事件会减少与当前实现的耦合。

最新更新