简体   繁体   English

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

[英]Testing async method using React testing library

I have button in component:我在组件中有按钮:

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

and method logout :和方法logout

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

Now I trying testing logout method by click on button:现在我尝试通过单击按钮测试注销方法:

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

Inside method logout in finally block I have props.history.push('/login') and I check this in my test: expect(history.location.pathname).toBe('/login') but test return error:finally块中的方法logout内部我有props.history.push('/login')并且我在我的测试中检查了这个: expect(history.location.pathname).toBe('/login')但测试返回错误:

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

Expected: "/login"
Received: "/"

You should use useHistory() hook to get history object inside your SFC.您应该使用useHistory()挂钩来获取 SFC 中的历史 object。

Besides, since the logout function is an async function, you should use waitFor method to wait for your expectations to pass.此外,由于logout function 是异步 function,您应该使用waitFor方法等待您的期望通过。

Eg例如

UserMenuComponent.tsx : 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 : 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');
    });
  });
});

test result:测试结果:

 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

You can use waitFor to wait for your expectation to pass.您可以使用waitFor等待您的期望通过。

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

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

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