Reactjs 未从react测试库中的.toHaveBeenCalledTimes()获取预期结果
无论如何,尝试测试函数在被激发后是否被调用。当我从该函数中获得一个Reactjs 未从react测试库中的.toHaveBeenCalledTimes()获取预期结果,reactjs,unit-testing,jestjs,react-testing-library,Reactjs,Unit Testing,Jestjs,React Testing Library,无论如何,尝试测试函数在被激发后是否被调用。当我从该函数中获得一个console.log时,firevent正在工作。但是.toHaveBeenCalledTimes(1)返回0。我错过了什么 如果我在父级中有handleLoginSubmit函数,并将其作为一个道具传递给子级,那么在测试中,一切都通过了。但是如果它在同一个组件中,它就会失败。如果有任何意义,请使用typescript 这是经过测试的 import React, { FC } from 'react'; type Event
console.log
时,firevent
正在工作。但是.toHaveBeenCalledTimes(1)
返回0。我错过了什么
如果我在父级中有handleLoginSubmit
函数,并将其作为一个道具传递给子级,那么在测试中,一切都通过了。但是如果它在同一个组件中,它就会失败。如果有任何意义,请使用typescript
这是经过测试的
import React, { FC } from 'react';
type Event = React.FormEvent<HTMLFormElement>;
interface Login {
handleLoginSubmit?: (event: Event) => React.ReactNode;
}
const Login: FC<Login> = () => {
const handleLoginSubmit = (_event: Event) => {
console.log('Firing' ); // This is logged
};
return (
<form data-testid='form' onSubmit={(event) => handleLoginSubmit(event)}>
<input data-testid='email'/>
<input data-testid='password'/>
<button data-testid='login-button'>login</button>
</form>
);
};
export default Login;
您不能断言是否要直接调用
handleLoginSubmit
函数。因为它是在Login
SFC的私有范围内定义的。您无法模拟或监视此函数,因为您无法访问它。所以,你需要间接地测试它。由于您在此函数中使用的是console.log
,因此我们可以监视console.log
。如果调用了它,则表示调用了handleLoginSubmit
函数
例如
index.tsx
:
import React,{FC}来自“React”;
类型事件=React.FormEvent;
界面登录{
handleLoginSubmit?:(事件:事件)=>React.ReactNode;
}
常量登录:FC=()=>{
const handleLoginSubmit=(\u event:event)=>{
控制台日志(“点火”);
};
返回(
handleLoginSubmit(事件)}>
登录
);
};
导出默认登录;
index.spec.tsx
:
从“@testing library/react”导入{render,firevent}”;
从“/”导入登录名;
从“React”导入React;
它(“应该处理ClickEvents”,()=>{
const logSpy=jest.spyOn(控制台,“日志”);
const{getByTestId}=render();
expect(getByTestId(“登录按钮”)).toBeTruthy();
fireEvent.submit(getByTestId(“表单”);
预期(logSpy)。已被催收时间(1);
});
100%覆盖率的单元测试结果:
PASS src/stackoverflow/59162138/index.spec.tsx
✓ 应处理ClickEvents(42毫秒)
console.log node_modules/jest mock/build/index.js:860
发射
-----------|----------|----------|----------|----------|-------------------|
文件|%Stmts |%Branch |%Funcs |%Line |未覆盖行|s|
-----------|----------|----------|----------|----------|-------------------|
所有文件| 100 | 100 | 100 | 100 ||
index.tsx | 100 | 100 | 100 | 100 ||
-----------|----------|----------|----------|----------|-------------------|
测试套件:1个通过,共1个
测试:1项通过,共1项
快照:共0个
时间:3.987秒,估计9秒
源代码:这里的问题是,您正在将
handleLoginSubmit
赋值给一个变量,但是其中的变量不同,尽管共享相同的名称(它在组件上的范围)。如果希望它工作,请将handleLoginSubmit
作为onSubmit
道具传递给组件,然后像render()
那样模拟道具,它将被称为onSubmit
道具传递是什么意思?您的意思是将它从父级传递到Login
组件吗?我不想这样做,因为我想在该组件中调用函数。啊,好的,所以当测试console.log(或其他控制台输出)时,我们需要在spy中指定它?所以,当测试lets say state时,我们需要一个间谍,它接受react,state或类似的参数?谢谢,顺便说一句!测试组件的状态,不要测试SFC中定义的功能的实现细节。这意味着函数(挂钩、事件处理程序等)将更改组件的状态。您应该声明组件的状态。好的,因此如果我想测试forms input changeevent,我不应该测试处理状态/事件的函数,而应该测试DOM中的输出/实际输入字段中的输出?@GameAtrix Yes。此外,如果更改事件处理程序是在SFC的私有范围中定义的,则无法访问它。所以,你不能添加间谍并模仿它。您需要测试组件的更新状态/属性(实际输入字段中的输出)
it('should handle ClickEvents', () => {
const handleLoginSubmit = jest.fn();
const { getByTestId } = render(<Login/>);
expect(getByTestId('login-button')).toBeTruthy();
fireEvent.submit(getByTestId('form'));
expect(handleLoginSubmit).toHaveBeenCalledTimes(1);
});
● Login page › should handle ClickEvents
expect(jest.fn()).toHaveBeenCalledTimes(expected)
Expected number of calls: 1
Received number of calls: 0
32 | fireEvent.submit(getByTestId('form'));
33 |
> 34 | expect(handleLoginSubmit).toHaveBeenCalledTimes(1);
| ^
35 |
36 | });
37 | });
at Object.it (__tests__/components/Login.test.tsx:34:31)