From a292fd409fb120dd95d10726100ad0c3964dcbbe Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Fri, 2 Oct 2026 16:29:57 -0700 Subject: [PATCH] test: fix three order-dependent and timing-flaky tests (#44271) * test(integration): answer the model-info refresh GET in the mixed MCP responses wire peer The proxy's periodic model-info refresh sends GET /v1/models to the deployment api_base, which tripped the peer's /responses-only assertion when a tick landed mid-test * test(e2e): wait for the api-keys URL after clicking Virtual Keys in onboarding /ui already renders the Virtual Keys heading, so the helper returned before navigation finished. The late route change moved focus and closed the account menu popover in hideLiteAdmin * test(proxy): stop two unit modules leaking app.openapi_schema and a session-wide Router test_custom_openapi cached a stripped schema on app.openapi_schema and never cleared it, breaking later openapi route tests. test_proxy_reject_logging built a module-level Router that stayed in the live router registry all session and re-added cost-map keys during a reload. Reset the schema via monkeypatch and make the Router a function-scoped fixture --- tests/e2e/ui/helpers/userOnboarding.ts | 1 + .../mcp/test_responses_mcp_mixed_tools.py | 2 ++ tests/unit/proxy/test_proxy_reject_logging.py | 30 ++++++++++--------- tests/unit/proxy/test_proxy_utils.py | 5 ++-- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/tests/e2e/ui/helpers/userOnboarding.ts b/tests/e2e/ui/helpers/userOnboarding.ts index 14e2b0257b2..9db3bb0867b 100644 --- a/tests/e2e/ui/helpers/userOnboarding.ts +++ b/tests/e2e/ui/helpers/userOnboarding.ts @@ -47,6 +47,7 @@ export async function expectUnrestrictedDashboard(page: Page): Promise { const session = await readDashboardSession(page); expect(session.password_reset_required === true, "login must not require a password reset").toBe(false); await virtualKeys.click(); + await expect(page).toHaveURL(/\/ui\/api-keys\/?$/); await expect(page.getByRole("main").getByRole("heading", { name: "Virtual Keys", exact: true })).toBeVisible({ timeout: 30_000, }); diff --git a/tests/integration/mcp/test_responses_mcp_mixed_tools.py b/tests/integration/mcp/test_responses_mcp_mixed_tools.py index 985a8b8a65e..91119f1c258 100644 --- a/tests/integration/mcp/test_responses_mcp_mixed_tools.py +++ b/tests/integration/mcp/test_responses_mcp_mixed_tools.py @@ -21,6 +21,8 @@ def test_responses_with_gateway_mcp_and_caller_function_tool_hands_both_to_model upstream_tools: list[tuple[str, ...]] = [] def respond(request: Request) -> Reply: + if request.method == "GET" and request.target.endswith("/models"): + return Reply(body=b'{"object":"list","data":[]}') assert request.target.endswith("/responses"), request.target body: Final = json.loads(request.body) upstream_tools.append(tuple(str(tool.get("name")) for tool in body.get("tools", ()))) diff --git a/tests/unit/proxy/test_proxy_reject_logging.py b/tests/unit/proxy/test_proxy_reject_logging.py index d5a3acb2cd7..4e250ed3c52 100644 --- a/tests/unit/proxy/test_proxy_reject_logging.py +++ b/tests/unit/proxy/test_proxy_reject_logging.py @@ -74,18 +74,20 @@ class testLogger(CustomLogger): self.reaches_sync_failure_event = True -router = Router( - model_list=[ - { - "model_name": "fake-model", - "litellm_params": { - "model": "openai/fake", - "api_base": "https://exampleopenaiendpoint-production.up.railway.app/", - "api_key": "sk-12345", - }, - } - ] -) +@pytest.fixture +def router() -> Router: + return Router( + model_list=[ + { + "model_name": "fake-model", + "litellm_params": { + "model": "openai/fake", + "api_base": "https://exampleopenaiendpoint-production.up.railway.app/", + "api_key": "sk-12345", + }, + } + ] + ) def _register_proxy_test_logger(callback_logger: testLogger) -> None: @@ -130,7 +132,7 @@ def _register_proxy_test_logger(callback_logger: testLogger) -> None: ], ) @pytest.mark.asyncio -async def test_chat_completion_request_with_redaction(route, body): +async def test_chat_completion_request_with_redaction(route, body, router, monkeypatch): """ IMPORTANT Enterprise Test - Do not delete it: Makes a /chat/completions request on LiteLLM Proxy @@ -139,7 +141,7 @@ async def test_chat_completion_request_with_redaction(route, body): """ from litellm.proxy import proxy_server - setattr(proxy_server, "llm_router", router) + monkeypatch.setattr(proxy_server, "llm_router", router) _test_logger = testLogger() _register_proxy_test_logger(_test_logger) litellm.set_verbose = True diff --git a/tests/unit/proxy/test_proxy_utils.py b/tests/unit/proxy/test_proxy_utils.py index ab787bbbe27..44ab2155734 100644 --- a/tests/unit/proxy/test_proxy_utils.py +++ b/tests/unit/proxy/test_proxy_utils.py @@ -1881,9 +1881,10 @@ async def test_health_check_not_called_when_disabled(monkeypatch): } }, ) -def test_custom_openapi(mock_get_openapi_schema): - from litellm.proxy.proxy_server import custom_openapi +def test_custom_openapi(mock_get_openapi_schema, monkeypatch): + from litellm.proxy.proxy_server import app, custom_openapi + monkeypatch.setattr(app, "openapi_schema", None) openapi_schema = custom_openapi() assert openapi_schema is not None