Reactjs 使用lodash.debounce延迟测试组件失败

Reactjs 使用lodash.debounce延迟测试组件失败,reactjs,jestjs,lodash,debounce,Reactjs,Jestjs,Lodash,Debounce,我有一个富格文本编辑器输入字段,我想用一个去模糊组件来包装它。去抖动输入组件如下所示: 从'react'导入{useState,useCallback}; 从“lodash.debounce”进口debounce; const useDebounce=(回调,延迟)=>{ const debouncedFn=useCallback( 去抖动((…args)=>回调(…args),延迟, [延迟]//如果延迟更改,将重新创建 ); 返回去Bouncedfn; }; 函数去BouncedInput(

我有一个富格文本编辑器输入字段,我想用一个去模糊组件来包装它。去抖动输入组件如下所示:

从'react'导入{useState,useCallback};
从“lodash.debounce”进口debounce;
const useDebounce=(回调,延迟)=>{
const debouncedFn=useCallback(
去抖动((…args)=>回调(…args),延迟,
[延迟]//如果延迟更改,将重新创建
);
返回去Bouncedfn;
};
函数去BouncedInput(props){
const[value,setValue]=使用状态(props.value);
const debouncedSave=useDebounce((nextValue)=>props.onChange(nextValue),props.delay);
常量handleChange=(下一个值)=>{
设置值(下一个值);
去BouncedSave(下一个值);
};
返回props.renderProps({onChange:handleChange,value});
}
导出默认的去BouncedInput;
我正在使用去BouncedInput作为MediumEditor的包装组件:

onTextChange(text)}
延迟={500}
renderProps={(道具)=>(
)}
/>;
MediumEditor组件执行一些我想测试的卫生工作,例如剥离html标记:

类MediumEditor扩展React.Component{
静态支柱={
id:PropTypes.string,
值:PropTypes.string,
onChange:PropTypes.func,
禁用:PropTypes.bool,
唯一标识:PropTypes.any,
占位符:PropTypes.string,
样式:PropTypes.object,
};
onChange(文本){
this.props.onChange(stripHtml(文本)=''?'':fixExcelPaste(文本));
}
render(){
常数{
身份证件
价值
一旦改变,
残废
占位符,
风格
独一无二的,
…其他道具
}=这是道具;
返回(
{禁用&&(
)}
this.onChange(text)}
text={value}
风格={{
风格
背景:已禁用?“透明”:“白色”,
边框颜色:禁用?“灰色”:“FF9600”,
溢出:“自动”,
颜色:“#444F55”,
}}
/>
);
}
}
导出默认MediumEditor;
我就是这样测试的:

it('如果有文本,则不剥离html标记',async()=>{
expect(editor.instance.state.text).toEqual('Lorem ipsum…?');
const mediumEditor=editor.findByProps({'data testid':'medium editor'});
常量newText='新文本,弗莱斯克

'; mediumEditor.props.onChange(新文本); //jest.runAllTimers(); expect(editor.instance.state.text).toEqual(newText); });
当我运行此测试时,我得到:

Error: expect(received).toEqual(expected) // deep equality

Expected: "<p><b>New text, Flesk</b></p>"
Received: "Lorem ipsum ...?"
我也尝试过:

jest.advancetimesbytime(500);
但是测试一直失败,我得到了文本的旧状态。 状态似乎出于某种原因没有改变,这很奇怪,因为在我用DebounceInput组件包装它们之前,组件曾经工作,测试是绿色的。 我拥有MediumEditor的父组件有一个方法onTextChange,应该从DebounceInput组件调用该方法,因为这是作为
onChange
属性传递给DebounceInput的函数,但是在测试中,我可以看出这种方法是永远达不到的。在浏览器中,一切正常,所以我不知道为什么它在测试中不工作

onTextChange(文本){
console.log('text',text);
this.setState((状态)=>{
返回{
任务:{…state.task,text},
是的,
};
});
}
进一步检查后,我可以看到正确的值在测试中一直通过去BouncedInput中的handleChange。因此,我怀疑,在这个测试中,lodash.debounce存在一些问题。我不确定我是应该模仿这个函数,还是模仿带有笑话

const handleChange=(nextValue)=>{
console.log(nextValue);
设置值(下一个值);
去BouncedSave(下一个值);
};
这就是我怀疑测试中存在问题的地方:

const useDebounce=(回调,延迟)=>{
const debouncedFn=useCallback(
去抖动((…args)=>回调(…args),延迟,
[延迟]//如果延迟更改,将重新创建
);
返回去Bouncedfn;
};
我试过这样嘲弄黛博斯:

从“lodash.debounce”导入去盎司
开玩笑的模仿('lodash.debounce');
mock实现(()=>jest.fn(fn=>fn));
这给了我一个错误:


我应该如何解决这个问题?

为什么不使用自己的去盎司实现呢?它很容易实现。在这方面:

导出函数UsedBouncedValue(状态、延迟){
常量[debouncedValue,setDebouncedValue]=useState(状态);
useffect(()=>{
常量超时=设置超时(()=>{
setDebouncedValue(状态);
},延误);
return()=>{
clearTimeout(超时);
};
},[状态,延迟];
返回去BouncedValue;

}
我猜您正在使用酶(从道具访问)。 为了测试依赖于
jest
中计时器的某些代码:

  • mark to jest在呼叫时使用假计时器
  • 渲染组件
  • 进行更改(这将启动计时器,在您的情况下是状态更改),注意当您从酶更改状态时,您需要调用
  • 使用
    jest.runOnlyPendingTimers()
  • 这应该行得通

    关于测试react组件的一些旁注:

  • 如果要测试
    onChange
    的功能,请测试立即组件(在您的案例中是
    MediumEditor
    ),测试onChange功能时,没有必要测试整个包装组件
  • 不要从测试中更新状态,它会使您的测试与特定的实现高度耦合、验证、重命名状态变量
    Error: Ran 100000 timers, and there are still more! Assuming we've hit an infinite recursion and bailing out...
    
    TypeError: _lodash.default.mockImplementation is not a function