使用 React 测试库测试异步方法

时间:2021-03-10 19:14:04

标签: reactjs react-router jestjs react-testing-library

我在组件中有按钮:

<button
    type="button"
    title="Logout"
    data-testid="logout"
    onClick={logout}
>

和方法logout

const logout = async () => {
    try {
        await authLogout()
    } catch (error) {
        console.error(error)
    } finally {
        props.history.push('/login')
    }
}

现在我尝试通过单击按钮来测试注销方法:

describe('UserMenuComponent', () => {
  it('go to login page after click on logout', async () => {
    const history = createMemoryHistory()

    const { getByTestId } = render(
      <Router history={history}>
        <UserMenuComponent />,
      </Router>,
      {
        initialState: { reducersAuth: initialState },
      },
    )

    fireEvent.click(getByTestId('logout'))
    expect(history.location.pathname).toBe('/login')
  })
})

logout 块中的内部方法 finally 我有 props.history.push('/login'),我在测试中检查了这个:expect(history.location.pathname).toBe('/login') 但测试返回错误:

expect(received).toBe(expected) // Object.is equality

Expected: "/login"
Received: "/"

2 个答案:

答案 0 :(得分:2)

您应该使用 useHistory() 钩子来获取 SFC 中的历史记录对象。

此外,由于 logout 函数是一个异步函数,您应该使用 waitFor 方法等待您的期望通过。

例如

UserMenuComponent.tsx

import React from 'react';
import { useHistory } from 'react-router-dom';

async function authLogout() {}

export function UserMenuComponent() {
  const history = useHistory();
  const logout = async () => {
    try {
      await authLogout();
    } catch (error) {
      console.error(error);
    } finally {
      history.push('/login');
    }
  };

  return <button type="button" title="Logout" data-testid="logout" onClick={logout}></button>;
}

UserMenuComponent.test.tsx

import { fireEvent, render, waitFor } from '@testing-library/react';
import React from 'react';
import { Router } from 'react-router-dom';
import { createMemoryHistory } from 'history';
import { UserMenuComponent } from './UserMenuComponent';

describe('UserMenuComponent', () => {
  it('go to login page after click on logout', async () => {
    const history = createMemoryHistory();
    const pushSpy = jest.spyOn(history, 'push');

    const { getByTestId } = render(
      <Router history={history}>
        <UserMenuComponent />,
      </Router>
    );

    fireEvent.click(getByTestId('logout'));
    await waitFor(() => {
      expect(pushSpy).toBeCalledWith('/login');
      expect(history.location.pathname).toBe('/login');
    });
  });
});

测试结果:

 PASS  examples/66571376/UserMenuComponent.test.tsx
  UserMenuComponent
    ✓ go to login page after click on logout (82 ms)

-----------------------|---------|----------|---------|---------|-------------------
File                   | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------------------|---------|----------|---------|---------|-------------------
All files              |   91.67 |      100 |     100 |   90.91 |                   
 UserMenuComponent.tsx |   91.67 |      100 |     100 |   90.91 | 12                
-----------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.881 s, estimated 4 s

答案 1 :(得分:0)

您可以使用 waitFor 等待您的期望通过。

await waitFor(() => expect(history.location.pathname).toBe('/login'))