React登录测试遇TypeError:options.agent属性类型不符求助
登录功能测试报错排查:TypeError: The "options.agent" property must be one of Agent-like Object, undefined, or false
错误信息
TypeError: The "options.agent" property must be one of Agent-like Object, undefined, or false. Received an instance of Object
测试代码
import { QueryClient, QueryClientProvider } from 'react-query'; import SignIn from '../SignIn'; import { setupServer } from 'msw/node' import { render, screen, fireEvent, waitFor, waitForElementToBeRemoved } from '@testing-library/react'; import { rest } from 'msw'; // 配置server模拟登录API请求 let server = setupServer(); beforeAll(() => server.listen()) // afterEach(() => server.resetHandlers()) afterAll(() => server.close()) const queryClient = new QueryClient(); const onSubmit = jest.fn(); beforeEach(() => { //onSubmit.mockClear(); render( <QueryClientProvider client={queryClient}> <SignIn onSuccess={onSubmit} /> </QueryClientProvider> ); }) describe('SignIn Domain', () => { test('Successful login', async () => { server.use( rest.post('/api/Auth/Login', (req, res, ctx) => { return res(ctx.json([{ token: 'myToken' }])); }), ); // 注意:这里getEmail()未定义,需替换为screen.getByLabelText('邮箱')之类的查询方法 await waitFor(() => { fireEvent.change(screen.getByLabelText('邮箱'), { target: { value: "myemail@gmail.com" } }) }); // 点击按钮 await waitFor(() => { fireEvent.click(screen.getByText('Continue')); }); await waitForElementToBeRemoved(screen.getByText('Processing...')); }) })
预期测试流程
- 输入邮箱
- 点击“Continue”(按钮变灰,加载时显示Spinner)
- 页面渲染密码输入框
- 输入密码
- 点击“Sign In”
项目依赖配置(package.json)
{ "name": "airdrop-app", "version": "0.1.0", "private": true, "dependencies": { "@fluentui/react": "^8.104.5", "@fluentui/react-icons": "^1.1.145", "@fluentui/react-icons-mdl2": "^1.3.29", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^11.2.7", "@testing-library/user-event": "^12.8.3", "@types/d3": "^6.7.5", "@types/file-saver": "^2.0.5", "@types/filesaver": "^0.0.30", "@types/geojson": "^7946.0.10", "@types/mapbox-gl": "^2.7.10", "@types/node": "^12.20.55", "@types/react": "^17.0.52", "@types/react-dom": "^17.0.18", "@types/react-motion": "0.0.29", "@types/react-router-dom": "^5.3.3", "axios": "^0.21.4", "d3": "^6.7.0", "d3-hexbin": "^0.2.2", "d3-svg-legend": "^2.25.6", "enzyme": "^3.11.0", "file-saver": "^2.0.5", "fluent": "^0.13.0", "formik": "^2.2.9", "mapbox-gl": "^2.12.0", "msw": "^0.28.2", "react": "^17.0.2", "react-cookie": "^4.1.1", "react-dom": "^17.0.2", "react-map-gl": "^6.1.21", "react-motion": "^0.5.2", "react-query": "^3.39.2", "react-rnd": "^10.4.1", "react-router-dom": "^5.3.4", "react-scripts": "5.0.1", "sprintf-js": "^1.1.2", "typescript": "^4.9.4", "web-vitals": "^1.1.2", "yup": "^0.32.11" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "jest", "eject": "react-scripts eject" }, "eslintConfig": { "extends": [ "react-app", "react-app/jest" ] }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }, "devDependencies": { "@types/d3-hexbin": "^0.2.3", "@types/enzyme": "^3.10.12", "@types/enzyme-adapter-react-16": "^1.0.6", "@types/sprintf-js": "^1.1.2", "enzyme-adapter-react-15": "^1.4.4", "enzyme-adapter-react-16": "^1.15.7", "jest": "^29.3.1", "jest-environment-jsdom": "^29.3.1", "ts-jest": "^29.0.3", "whatwg-fetch": "^3.6.2" } }
问题排查与解决方案
核心原因
这个错误是因为msw@0.28.2(旧版本)与jest@29.x的HTTP Agent不兼容,旧版msw在处理请求时传递的agent格式不符合Node.js最新版本的要求。另外测试代码本身也存在一些语法和逻辑问题。
分步解决
更新msw到兼容版本
旧版msw(0.28.x)不支持jest29,建议升级到0.35.x及以上版本:npm install msw@^0.35.0 --save-dev升级后无需大幅修改测试代码,0.35.x仍支持
setupServer的旧用法。修复测试代码中的语法/逻辑问题
- 取消注释
afterEach(() => server.resetHandlers()),避免不同测试用例的请求处理逻辑互相污染。 - 替换未定义的
getEmail(),改用screen提供的查询方法,比如screen.getByLabelText('邮箱')(根据SignIn组件的实际label调整)。 - 修正测试函数的闭合括号:把
)}改成})(共两处)。
- 取消注释
可选:调整axios配置(若更新msw后仍报错)
如果SignIn组件使用axios发送请求,可在axios实例中显式禁用agent:import axios from 'axios'; const apiClient = axios.create({ // 其他配置 httpAgent: false, httpsAgent: false, });
修正后的测试代码片段
// 恢复afterEach重置handler afterEach(() => server.resetHandlers()) // ... test('Successful login', async () => { server.use( rest.post('/api/Auth/Login', (req, res, ctx) => { return res(ctx.json([{ token: 'myToken' }])); }), ); // 替换为实际的邮箱输入框查询方式 const emailInput = screen.getByLabelText('邮箱'); fireEvent.change(emailInput, { target: { value: "myemail@gmail.com" } }); fireEvent.click(screen.getByText('Continue')); await waitForElementToBeRemoved(screen.getByText('Processing...')); // 后续可添加密码输入和SignIn点击的测试逻辑 })
内容的提问来源于stack exchange,提问作者T-O
相关产品推荐
相关产品推荐

