【问题标题】:How can I test my protected route with an authcontext with jest and react-testing-library如何使用带有 jest 和 react-testing-library 的 authcontext 测试我的受保护路由
【发布时间】:2021-07-14 23:04:49
【问题描述】:

我有一个带有受保护路由组件的 react 应用:

import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { AuthConsumer } from '../../Utils/contexts/AuthContext.js';

const ProtectedRoute = ({ component: Component, ...rest }) => {

  
  return (
    <AuthConsumer>
  {({ currentUser }) => (    <Route {...rest} render={
          props => {
            if ({ currentUser }) {
              return <Component {...rest} {...props} />
            } else {
              return <Redirect to={
                {
                  pathname: '/unauthorized',
                  state: {
                    from: props.location
                  }
                }
              } />
            }
          }
        } />)}
      </AuthConsumer>
  )
}

export default ProtectedRoute; 

ProtectedRoute 使用授权上下文:

import React, { useEffect, useState } from 'react';
import firebase from '../firebase';

const AuthContext = React.createContext();

export const AuthProvider = ({ children }) => {
    const [ currentUser, setCurrentUser ] = useState(null);

    useEffect(() => {
        firebase.auth().onAuthStateChanged((user) => setCurrentUser(user));
    }, [currentUser]);

    return (
        <AuthContext.Provider
            value={{
                currentUser
            }}
        >
            {children}
        </AuthContext.Provider>
    );
};

export const AuthConsumer = AuthContext.Consumer

我想通过 jest 和 react-testing-library 来测试当 currentUser 存在时路由是否有效,而当一个不存在时无效。到目前为止,我的测试是:

import React from 'react'
import Info from '../../pages/Info/info'

import {
  render,
  screen,
  fireEvent,
} from '../../Utils/test-utils/testing-library-utils'
import ProtectedRoute from './protectedRoute'

jest.mock('../../pages/Info/info', () => {
  return jest.fn(() => null)
})

const AuthContext = React.createContext()
const currentUser = {
  uid: 1,
}

describe('protected route works with authenticated users', () => {
  test('can login when user is authenticated', () => {
    render(
      <AuthContext.Provider
        value={{
          currentUser,
        }}>
        <ProtectedRoute component={<Info />} />
      </AuthContext.Provider>
    )
    const returnedRoute = screen.queryByTestId('currentuser-valid')
    console.log('RETURNED ROUTE', returnedRoute)
    expect(returnedRoute).toBeNull()
  })
})

我似乎无法将假的 currentUser 对象传递给 ProtectedRoute - 我总是得到“TypeError: Cannot destructure property currentUser of 'undefined' or 'null'。”

如何模拟 AuthContext?我该怎么做才能将它作为 currentUser 传递一个有效或无效的值,从而使测试通过或失败?

【问题讨论】:

  • 我在变量范围方面遇到了类似的问题。这是一个很长的镜头,但是您可以尝试在test 方法中创建currentUser 变量吗?
  • 这似乎没有什么不同 - 不知何故 currentUser 的值没有被使用?

标签: reactjs firebase-authentication jestjs mocking react-testing-library


【解决方案1】:

AuthContext 的提供者和消费者应该是一对。您不应该在测试用例中创建新的上下文。在ProtectedRoute 组件文件和测试文件中继续使用相同的AuthContext

例如

ProtectedRoute.tsx:

import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { AuthConsumer } from './AuthContext';

const ProtectedRoute = ({ component: Component, ...rest }) => {
  return (
    <AuthConsumer>
      {({ currentUser }) => (
        <Route
          {...rest}
          render={(props) => {
            console.log('currentUser: ', currentUser);
            if (currentUser) {
              return <Component {...rest} {...props} />;
            } else {
              return (
                <Redirect
                  to={{
                    pathname: '/unauthorized',
                    state: {
                      from: props.location,
                    },
                  }}
                />
              );
            }
          }}
        />
      )}
    </AuthConsumer>
  );
};

export default ProtectedRoute;

AuthContext.tsx:

import React, { useState } from 'react';

interface Context {
  currentUser: { uid: number } | null;
}
export const AuthContext = React.createContext<Context>({ currentUser: null });

export const AuthProvider = ({ children }) => {
  const [currentUser, setCurrentUser] = useState(null);
  return <AuthContext.Provider value={{ currentUser }}>{children}</AuthContext.Provider>;
};

export const AuthConsumer = AuthContext.Consumer;

Info.tsx:

import React from 'react';

export function Info() {
  return <div>info</div>;
}

ProtectedRoute.test.tsx:

import React from 'react';
import { render, screen } from '@testing-library/react';
import ProtectedRoute from './protectedRoute';
import { AuthContext } from './AuthContext';
import { MemoryRouter } from 'react-router-dom';
import { Info } from './Info';

const currentUser = { uid: 1 };

describe('protected route works with authenticated users', () => {
  test('can login when user is authenticated', () => {
    render(
      <AuthContext.Provider value={{ currentUser }}>
        <MemoryRouter initialEntries={['/']}>
          <ProtectedRoute component={Info} />
        </MemoryRouter>
      </AuthContext.Provider>
    );
    expect(screen.queryByTestId('protected-component')).toBeDefined();
  });
});

测试结果:

 PASS  examples/67184212/ProtectedRoute.test.tsx (7.628 s)
  protected route works with authenticated users
    ✓ can login when user is authenticated (73 ms)

  console.log
    currentUser:  { uid: 1 }

      at render (examples/67184212/ProtectedRoute.tsx:12:21)

--------------------|---------|----------|---------|---------|-------------------
File                | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
--------------------|---------|----------|---------|---------|-------------------
All files           |   86.96 |       50 |      80 |      85 |                   
 AuthContext.tsx    |   71.43 |      100 |       0 |   66.67 | 9-10              
 Info.tsx           |     100 |      100 |     100 |     100 |                   
 ProtectedRoute.tsx |   92.31 |       50 |     100 |   90.91 | 16                
--------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        8.169 s

软件包版本:

"@testing-library/react": "^11.2.2",
"react": "^16.14.0",
"react-router-dom": "^5.2.0",

【讨论】:

    猜你喜欢
    • 2021-02-11
    • 2020-03-22
    • 2021-02-28
    • 1970-01-01
    • 1970-01-01
    • 2020-05-14
    • 2021-05-25
    • 2020-03-24
    • 1970-01-01
    相关资源
    最近更新 更多