运行单元测试时,useEffect挂钩中的React useState挂钩未设置状态

时间:2020-07-21 13:01:54

标签: reactjs unit-testing

我正在学习React,现在正在尝试单元测试。我具有以下代码片段的登录功能组件:

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

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

当我运行该应用程序时,一切正常。但是,当我尝试为此运行测试时,它不会将用户设置为state。这是我编写的模拟和测试:

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  
});

可以正确提供模拟服务,并且可以正确解析模拟的用户数据,但是setUsers(allUsers)实际上并未通过测试进行设置。在效果内部,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

这里是使用状态的函数。在运行应用程序时它可以工作,但是在运行测试时,用户仍然是空数组。

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');
 }
};

有任何同伴吗?

1 个答案:

答案 0 :(得分:0)

setState不会更改局部变量(这在js中是不可能的,尤其是在使用const时)。 它只是确保在下一个渲染器中调用useState将返回新​​值。

  • 如果需要在新位置设置新值,请使用相同的变量(allUsers)。
  • 如果您在其他地方需要新值,则会在状态变量(用户)中看到它。