test: use real HTTP responses and plugin tool clients (#43364)

This commit is contained in:
Asuka Minato authored and GitHub committed 2026-10-04 11:38:23 +00:00
1 parent 1cbb6dc385
commit 16bbfc50bd
3 files changed
+50 -36

No files matched your search

@@ -1,9 +1,11 @@
from __future__ import annotations
from unittest.mock import Mock, patch
import json
import httpx
import pytest
import core.plugin.impl.base as plugin_client_module
from core.tools.entities.common_entities import I18nObject
from core.tools.entities.tool_entities import (
ToolEntity,
@@ -63,27 +65,29 @@ def test_plugin_tool_provider_controller_basic_behaviors():
controller.get_tool("missing")
def test_validate_credentials_success():
@pytest.mark.parametrize("valid", [True, False])
def test_validate_credentials(monkeypatch: pytest.MonkeyPatch, valid: bool):
controller = _build_controller()
manager = Mock()
manager.validate_provider_credentials.return_value = True
requests: list[httpx.Request] = []
with patch("core.tools.plugin_tool.provider.PluginToolManager", return_value=manager):
controller._validate_credentials(user_id="u1", credentials={"api_key": "x"})
def handle_request(request: httpx.Request) -> httpx.Response:
requests.append(request)
return httpx.Response(200, json={"code": 0, "message": "", "data": {"result": valid}})
manager.validate_provider_credentials.assert_called_once_with(
tenant_id="tenant-1",
user_id="u1",
provider="provider-a",
credentials={"api_key": "x"},
)
def test_validate_credentials_failure():
controller = _build_controller()
manager = Mock()
manager.validate_provider_credentials.return_value = False
with patch("core.tools.plugin_tool.provider.PluginToolManager", return_value=manager):
with pytest.raises(ToolProviderCredentialValidationError, match="Invalid credentials"):
with httpx.Client(transport=httpx.MockTransport(handle_request)) as client:
monkeypatch.setattr(plugin_client_module, "_httpx_client", client)
if valid:
controller._validate_credentials(user_id="u1", credentials={"api_key": "x"})
else:
with pytest.raises(ToolProviderCredentialValidationError, match="Invalid credentials"):
controller._validate_credentials(user_id="u1", credentials={"api_key": "x"})
assert len(requests) == 1
request = requests[0]
assert request.method == "POST"
assert request.url.path.endswith("/plugin/tenant-1/dispatch/tool/validate_credentials")
assert request.headers["X-Plugin-ID"] == "langgenius/provider-a"
assert json.loads(request.content) == {
"user_id": "u1",
"data": {"provider": "provider-a", "credentials": {"api_key": "x"}},
}
@@ -7,7 +7,7 @@ remote HTTP remain mocked because they are external I/O boundaries.
from __future__ import annotations
from collections.abc import Iterator
from unittest.mock import Mock, patch
from unittest.mock import patch
from uuid import UUID, uuid4
import httpx
@@ -119,10 +119,12 @@ def test_create_file_by_raw_prefers_filename_extension_over_mimetype(
def test_create_file_by_url_downloads_and_persists_record(sqlite_tool_file_session: Session) -> None:
manager = ToolFileManager()
tenant_id = str(uuid4())
response = Mock()
response.content = b"binary"
response.headers = {"Content-Type": "application/octet-stream"}
response.raise_for_status.return_value = None
response = httpx.Response(
200,
content=b"binary",
headers={"Content-Type": "application/octet-stream"},
request=httpx.Request("GET", "https://example.com/f.bin"),
)
with (
patch("core.tools.tool_file_manager.storage") as storage,
@@ -143,10 +145,12 @@ def test_create_file_by_url_prefers_url_extension_over_mimetype(
) -> None:
manager = ToolFileManager()
tenant_id = str(uuid4())
response = Mock()
response.content = b"docx"
response.headers = {"Content-Type": "application/octet-stream"}
response.raise_for_status.return_value = None
response = httpx.Response(
200,
content=b"docx",
headers={"Content-Type": "application/octet-stream"},
request=httpx.Request("GET", "https://example.com/report.docx?download=1"),
)
with (
patch("core.tools.tool_file_manager.storage") as storage,
@@ -1,7 +1,8 @@
from json.decoder import JSONDecodeError
from typing import Any
from unittest.mock import Mock, patch
from unittest.mock import patch
import httpx
import pytest
from flask import Flask
from yaml import YAMLError
@@ -326,16 +327,20 @@ def test_parse_openai_plugin_json_branches(app):
def test_parse_openai_plugin_json_http_branches(app):
with app.test_request_context():
response = type("Resp", (), {"status_code": 500, "text": "", "close": Mock()})()
response = httpx.Response(500, stream=httpx.ByteStream(b""))
assert not response.is_closed
with patch("core.tools.utils.parser.ssrf_proxy.get", return_value=response):
with pytest.raises(ToolProviderNotFoundError, match="cannot get openapi yaml"):
ApiBasedToolSchemaParser.parse_openai_plugin_json_to_tool_bundle(
'{"api": {"url": "https://x", "type": "openapi"}}'
)
response.close.assert_called_once()
assert response.is_closed
success_response = type("Resp", (), {"status_code": 200, "text": "openapi: 3.0.0", "close": Mock()})()
with patch("core.tools.utils.parser.ssrf_proxy.get", return_value=success_response):
success_response = httpx.Response(200, text="openapi: 3.0.0")
with (
patch("core.tools.utils.parser.ssrf_proxy.get", return_value=success_response),
patch.object(success_response, "close", wraps=success_response.close) as close,
):
with patch(
"core.tools.utils.parser.ApiBasedToolSchemaParser.parse_openapi_yaml_to_tool_bundle",
return_value=["bundle"],
@@ -345,7 +350,8 @@ def test_parse_openai_plugin_json_http_branches(app):
)
assert bundles == ["bundle"]
mock_parse.assert_called_once()
success_response.close.assert_called_once()
close.assert_called_once_with()
assert success_response.is_closed
def test_auto_parse_json_yaml_failure():