You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React应用结合AWS Cognito测试:模拟用户数据遇阻求助

问题描述

使用React Testing Library、MSW和Vitest进行测试时,模拟AWS Cognito数据遇到问题,运行测试时会抛出NotAuthorizedException: Incorrect username or password或No current user错误。以下是相关代码:

setup.ts

import { cleanup } from '@testing-library/react';
import '@testing-library/jest-dom/vitest';
import { server } from '../mocks/server';
import Amplify, { Auth } from 'aws-amplify';
import { env } from 'process';

Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: vi.fn().mockImplementation((query) => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: vi.fn(), // deprecated
    removeListener: vi.fn(), // deprecated
    addEventListener: vi.fn(),
    removeEventListener: vi.fn(),
    dispatchEvent: vi.fn(),
  })),
});
const { getComputedStyle } = window;

beforeAll(async () => {
  window.getComputedStyle = (elt) => getComputedStyle(elt);
  server.listen({ onUnhandledRequest: 'bypass' });
  Amplify.configure({
    Auth: {
      region: env.REACT_APP_COGNITO_REGION,
      userPoolId: env.REACT_APP_COGNITO_USER_POOL_ID,
      userPoolWebClientId: env.REACT_APP_COGNITO_USER_POOL_WEB_CLIENT_ID,
      identityPoolId: env.REACT_APP_COGNITO_IDENTITY_POOL_ID,
    },
  });
});

afterEach(() => {
  server.resetHandlers();
  cleanup();
});
afterAll(() => server.close());

示例测试代码

import { render, screen, waitFor } from '@testing-library/react';
import { UsersList } from './UsersList';
import { BrowserRouter } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const reactQueryClient = new QueryClient();
const MockUsersList = () => {
  return (
    <QueryClientProvider client={reactQueryClient}>
      <BrowserRouter>
        <UsersList />
      </BrowserRouter>
    </QueryClientProvider>
  );
};

describe('UsersList', () => {
  beforeAll(
    async () =>
      await Auth.signIn('test@test.com', 'test!')
  );
  it('render a list of users', async () => {
    render(<MockUsersList />);
    await waitFor(() => {
      expect(
        screen.getByText('test@test.com')
      ).toBeInTheDocument();
    });
  });
});
解决方案

核心思路是Mock AWS Amplify Auth模块,避免调用真实的Cognito服务,直接返回模拟的用户认证数据。

1. 在测试文件中局部Mock Auth

在测试文件顶部添加Mock逻辑,覆盖Auth的关键方法:

// 测试文件顶部
vi.mock('aws-amplify', async () => {
  const actual = await vi.importActual('aws-amplify');
  return {
    ...actual,
    Auth: {
      ...actual.Auth,
      // Mock登录方法,返回模拟用户
      signIn: vi.fn().mockResolvedValue({
        username: 'test@test.com',
        attributes: { email: 'test@test.com' },
        // 按需添加其他用户属性
      }),
      // Mock获取当前已认证用户的方法,避免"No current user"错误
      currentAuthenticatedUser: vi.fn().mockResolvedValue({
        username: 'test@test.com',
        attributes: { email: 'test@test.com' },
      }),
      // 如果组件用到其他Auth方法(如signOut、currentUserInfo),需同步Mock
    },
  };
});

然后修改测试块,移除真实的Auth.signIn调用:

describe('UsersList', () => {
  // 移除原beforeAll中的Auth.signIn调用,Mock方法会直接返回模拟数据
  it('render a list of users', async () => {
    render(<MockUsersList />);
    await waitFor(() => {
      expect(screen.getByText('test@test.com')).toBeInTheDocument();
    });
  });
});

2. 全局Mock Auth(可选)

如果多个测试文件都需要模拟Cognito用户,可以在setup.ts中配置全局Mock:

// setup.ts中添加
vi.mock('aws-amplify', async () => {
  const actual = await vi.importActual('aws-amplify');
  return {
    ...actual,
    Auth: {
      ...actual.Auth,
      signIn: vi.fn().mockResolvedValue({ username: 'test@test.com', attributes: { email: 'test@test.com' } }),
      currentAuthenticatedUser: vi.fn().mockResolvedValue({ username: 'test@test.com', attributes: { email: 'test@test.com' } }),
      // 按需添加其他需要Mock的Auth方法
    },
  };
});

注意事项

  • 不要在测试中调用真实的Auth.signIn,否则会依赖外部Cognito服务,导致认证错误。
  • 需根据组件实际使用的Auth方法,同步Mock对应的实现,确保组件能获取到预期的认证状态和用户数据。
  • 如果组件直接调用Cognito的REST API(而非通过Amplify Auth封装),则需要用MSW添加对应的请求Mock。

内容的提问来源于stack exchange,提问作者Radoslaw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 02:57:47