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
相关产品推荐
相关产品推荐

