简体   繁体   English

运行单元测试时,在useEffect钩子中反应useState钩子没有设置state

[英]React useState hook inside useEffect hook does not set state when running unit tests

I am learning React and am now trying out unit testing.我正在学习 React,现在正在尝试单元测试。 I have login functional component with this following code fragment:我有带有以下代码片段的登录功能组件:

const [users, setUsers] = useState<User[]>([]);

useEffect(() => {
  usersService.getUsers().then((allUsers: User[]) => {
    setUsers(allUsers);
  });
}, []); // eslint-disable-line react-hooks/exhaustive-deps

It all works just fine when I run the app.当我运行应用程序时,一切正常。 However, when I try to run the test for this, it does not set the users to state.但是,当我尝试为此运行测试时,它不会将用户设置为 state。 Here is a mock and a test that I wrote:这是我写的一个模拟和一个测试:

const usersServiceMock: UsersService = {
  getUsers: (): Promise<User[]> => {
    return new Promise((resolve) => {
      process.nextTick(() =>
        resolve([{ username: 'test', password: 'test', imageUrl: '', id: 0 } as User])
      );
    });
  },
} as UsersService;

it('logs user in', async () => {
  const loginSpy = jest.spyOn(loginServiceMock, 'logUserIn');
  const usersSpy = jest.spyOn(usersServiceMock, 'getUsers');

  const component = render(
    <Login loginService={loginServiceMock} usersService={usersServiceMock} />
  );

  expect(usersSpy).toHaveBeenCalledTimes(1);
  //up until here, test is fine, but users are not set inside component  
});

Mock service is provided properly and mocked user data is properly resolved but setUsers(allUsers) does not actually set it with tests.正确提供了模拟服务,并且正确解析了模拟用户数据,但 setUsers(allUsers) 实际上并未通过测试对其进行设置。 Inside the effect, usersService.getUsers() does get mocked data but it never sets it.在效果内部, usersService.getUsers() 确实获得了模拟数据,但它从未设置它。

const [users, setUsers] = useState<User[]>([]);

useEffect(() => {
  usersService.getUsers().then((allUsers: User[]) => {
    // allUsers value is [{ username: 'test', password: 'test', imageUrl: '', id: 0}]        
    setUsers(allUsers);
    // users value is []
  });
}, []); // eslint-disable-line react-hooks/exhaustive-deps

Here is function that uses the state.这是使用 state 的 function。 It works when running the app, but when running tests, users is still empty array.它在运行应用程序时有效,但在运行测试时,用户仍然是空数组。

const login = (): void => {
const userFromDb = users.find((u) => u.username === user.username);
if (!userFromDb || userFromDb.password !== user.password) {
  setUser({
    username: '',
    password: '',
    imageUrl: '',
  });
  setIsDialogOpen(true);
 } else {
  loginService.logUserIn(userFromDb);
  history.push('/home');
 }
};

Any ides?有什么想法吗?

setState does not change the local variable (this is impossible in js, especially when using const). setState不会改变局部变量(这在 js 中是不可能的,尤其是在使用 const 时)。 It just ensures that calling the useState in the next render will return the new value.它只是确保在下一次渲染中调用 useState 将返回新值。

  • If you need the new value where you set it, jus use the same variable (allUsers).如果您需要设置它的新值,只需使用相同的变量 (allUsers)。
  • If you need the new value elsewhere, you will see it in the state variable (users).如果您在其他地方需要新值,您将在 state 变量(用户)中看到它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM