Skip to content

Commit 0db4cae

Browse files
lesebclaude
andcommitted
fix(test): update bing and tavily tests for persistent client refactor
Upstream refactored search providers to use a persistent self._client instead of creating a new httpx.AsyncClient per request. Update test fixtures to set _client directly with a MagicMock instead of patching the httpx.AsyncClient class methods. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Sébastien Han <seb@redhat.com>
1 parent f68548e commit 0db4cae

2 files changed

Lines changed: 132 additions & 128 deletions

File tree

tests/unit/providers/tool_runtime/test_bing_search.py

Lines changed: 64 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# This source code is licensed under the terms described in the LICENSE file in
55
# the root directory of this source tree.
66

7-
from unittest.mock import AsyncMock, patch
7+
from unittest.mock import AsyncMock, MagicMock
88

99
import httpx
1010
import pytest
@@ -15,7 +15,9 @@
1515

1616
@pytest.fixture
1717
def bing_search():
18-
return BingSearchToolRuntimeImpl(BingSearchToolConfig(api_key="test-key", top_k=3))
18+
impl = BingSearchToolRuntimeImpl(BingSearchToolConfig(api_key="test-key", top_k=3))
19+
impl._client = MagicMock(spec=httpx.AsyncClient)
20+
return impl
1921

2022

2123
@pytest.fixture
@@ -39,79 +41,79 @@ def mock_bing_response():
3941

4042

4143
async def test_invoke_with_allowed_domains(bing_search, mock_bing_response):
42-
with patch("httpx.AsyncClient.get", new_callable=AsyncMock, return_value=mock_bing_response) as mock_get:
43-
await bing_search.invoke_tool(
44-
"web_search",
45-
{
46-
"query": "test query",
47-
"allowed_domains": ["example.com", "docs.example.com"],
48-
},
49-
)
50-
call_kwargs = mock_get.call_args
51-
query_param = call_kwargs.kwargs["params"]["q"]
52-
assert "site:example.com" in query_param
53-
assert "site:docs.example.com" in query_param
54-
assert query_param == "test query (site:example.com OR site:docs.example.com)"
44+
bing_search._client.get = AsyncMock(return_value=mock_bing_response)
45+
await bing_search.invoke_tool(
46+
"web_search",
47+
{
48+
"query": "test query",
49+
"allowed_domains": ["example.com", "docs.example.com"],
50+
},
51+
)
52+
call_kwargs = bing_search._client.get.call_args
53+
query_param = call_kwargs.kwargs["params"]["q"]
54+
assert "site:example.com" in query_param
55+
assert "site:docs.example.com" in query_param
56+
assert query_param == "test query (site:example.com OR site:docs.example.com)"
5557

5658

5759
async def test_invoke_with_user_location_country(bing_search, mock_bing_response):
58-
with patch("httpx.AsyncClient.get", new_callable=AsyncMock, return_value=mock_bing_response) as mock_get:
59-
await bing_search.invoke_tool(
60-
"web_search",
61-
{
62-
"query": "test query",
63-
"user_location": {"country": "US", "city": "San Francisco"},
64-
},
65-
)
66-
call_kwargs = mock_get.call_args
67-
assert call_kwargs.kwargs["params"]["cc"] == "US"
60+
bing_search._client.get = AsyncMock(return_value=mock_bing_response)
61+
await bing_search.invoke_tool(
62+
"web_search",
63+
{
64+
"query": "test query",
65+
"user_location": {"country": "US", "city": "San Francisco"},
66+
},
67+
)
68+
call_kwargs = bing_search._client.get.call_args
69+
assert call_kwargs.kwargs["params"]["cc"] == "US"
6870

6971

7072
async def test_invoke_with_search_context_size(bing_search, mock_bing_response):
71-
with patch("httpx.AsyncClient.get", new_callable=AsyncMock, return_value=mock_bing_response) as mock_get:
72-
await bing_search.invoke_tool(
73-
"web_search",
74-
{
75-
"query": "test query",
76-
"search_context_size": "high",
77-
},
78-
)
79-
call_kwargs = mock_get.call_args
80-
assert call_kwargs.kwargs["params"]["count"] == 10
73+
bing_search._client.get = AsyncMock(return_value=mock_bing_response)
74+
await bing_search.invoke_tool(
75+
"web_search",
76+
{
77+
"query": "test query",
78+
"search_context_size": "high",
79+
},
80+
)
81+
call_kwargs = bing_search._client.get.call_args
82+
assert call_kwargs.kwargs["params"]["count"] == 10
8183

8284

8385
async def test_invoke_without_extra_params(bing_search, mock_bing_response):
84-
with patch("httpx.AsyncClient.get", new_callable=AsyncMock, return_value=mock_bing_response) as mock_get:
85-
await bing_search.invoke_tool(
86-
"web_search",
87-
{"query": "test query"},
88-
)
89-
call_kwargs = mock_get.call_args
90-
params = call_kwargs.kwargs["params"]
91-
assert params["q"] == "test query"
92-
assert params["count"] == 3
93-
assert "cc" not in params
86+
bing_search._client.get = AsyncMock(return_value=mock_bing_response)
87+
await bing_search.invoke_tool(
88+
"web_search",
89+
{"query": "test query"},
90+
)
91+
call_kwargs = bing_search._client.get.call_args
92+
params = call_kwargs.kwargs["params"]
93+
assert params["q"] == "test query"
94+
assert params["count"] == 3
95+
assert "cc" not in params
9496

9597

9698
async def test_invoke_with_empty_allowed_domains(bing_search, mock_bing_response):
97-
with patch("httpx.AsyncClient.get", new_callable=AsyncMock, return_value=mock_bing_response) as mock_get:
98-
await bing_search.invoke_tool(
99-
"web_search",
100-
{
101-
"query": "test query",
102-
"allowed_domains": [],
103-
},
104-
)
105-
call_kwargs = mock_get.call_args
106-
assert call_kwargs.kwargs["params"]["q"] == "test query"
99+
bing_search._client.get = AsyncMock(return_value=mock_bing_response)
100+
await bing_search.invoke_tool(
101+
"web_search",
102+
{
103+
"query": "test query",
104+
"allowed_domains": [],
105+
},
106+
)
107+
call_kwargs = bing_search._client.get.call_args
108+
assert call_kwargs.kwargs["params"]["q"] == "test query"
107109

108110

109111
async def test_invoke_returns_source_metadata(bing_search, mock_bing_response):
110112
"""Test that invoke_tool returns source URLs in metadata."""
111-
with patch("httpx.AsyncClient.get", new_callable=AsyncMock, return_value=mock_bing_response):
112-
result = await bing_search.invoke_tool(tool_name="web_search", kwargs={"query": "test query"})
113-
assert result.metadata is not None
114-
assert "sources" in result.metadata
115-
assert len(result.metadata["sources"]) == 1
116-
assert result.metadata["sources"][0]["url"] == "https://example.com"
117-
assert result.metadata["query"] == "test query"
113+
bing_search._client.get = AsyncMock(return_value=mock_bing_response)
114+
result = await bing_search.invoke_tool(tool_name="web_search", kwargs={"query": "test query"})
115+
assert result.metadata is not None
116+
assert "sources" in result.metadata
117+
assert len(result.metadata["sources"]) == 1
118+
assert result.metadata["sources"][0]["url"] == "https://example.com"
119+
assert result.metadata["query"] == "test query"

tests/unit/providers/tool_runtime/test_tavily_search.py

Lines changed: 68 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# This source code is licensed under the terms described in the LICENSE file in
55
# the root directory of this source tree.
66

7-
from unittest.mock import AsyncMock, patch
7+
from unittest.mock import AsyncMock, MagicMock
88

99
import httpx
1010
import pytest
@@ -15,7 +15,9 @@
1515

1616
@pytest.fixture
1717
def tavily_search():
18-
return TavilySearchToolRuntimeImpl(TavilySearchToolConfig(api_key="test-key", max_results=3))
18+
impl = TavilySearchToolRuntimeImpl(TavilySearchToolConfig(api_key="test-key", max_results=3))
19+
impl._client = MagicMock(spec=httpx.AsyncClient)
20+
return impl
1921

2022

2123
@pytest.fixture
@@ -38,83 +40,83 @@ def mock_tavily_response():
3840

3941

4042
async def test_invoke_with_allowed_domains(tavily_search, mock_tavily_response):
41-
with patch("httpx.AsyncClient.post", new_callable=AsyncMock, return_value=mock_tavily_response) as mock_post:
42-
await tavily_search.invoke_tool(
43-
"web_search",
44-
{
45-
"query": "test query",
46-
"allowed_domains": ["example.com", "docs.example.com"],
47-
},
48-
)
49-
call_kwargs = mock_post.call_args
50-
request_body = call_kwargs.kwargs["json"]
51-
assert request_body["include_domains"] == ["example.com", "docs.example.com"]
43+
tavily_search._client.post = AsyncMock(return_value=mock_tavily_response)
44+
await tavily_search.invoke_tool(
45+
"web_search",
46+
{
47+
"query": "test query",
48+
"allowed_domains": ["example.com", "docs.example.com"],
49+
},
50+
)
51+
call_kwargs = tavily_search._client.post.call_args
52+
request_body = call_kwargs.kwargs["json"]
53+
assert request_body["include_domains"] == ["example.com", "docs.example.com"]
5254

5355

5456
async def test_invoke_with_search_context_size(tavily_search, mock_tavily_response):
55-
with patch("httpx.AsyncClient.post", new_callable=AsyncMock, return_value=mock_tavily_response) as mock_post:
56-
await tavily_search.invoke_tool(
57-
"web_search",
58-
{
59-
"query": "test query",
60-
"search_context_size": "high",
61-
},
62-
)
63-
call_kwargs = mock_post.call_args
64-
request_body = call_kwargs.kwargs["json"]
65-
assert request_body["max_results"] == 10
57+
tavily_search._client.post = AsyncMock(return_value=mock_tavily_response)
58+
await tavily_search.invoke_tool(
59+
"web_search",
60+
{
61+
"query": "test query",
62+
"search_context_size": "high",
63+
},
64+
)
65+
call_kwargs = tavily_search._client.post.call_args
66+
request_body = call_kwargs.kwargs["json"]
67+
assert request_body["max_results"] == 10
6668

6769

6870
async def test_invoke_without_extra_params(tavily_search, mock_tavily_response):
69-
with patch("httpx.AsyncClient.post", new_callable=AsyncMock, return_value=mock_tavily_response) as mock_post:
70-
await tavily_search.invoke_tool(
71-
"web_search",
72-
{"query": "test query"},
73-
)
74-
call_kwargs = mock_post.call_args
75-
request_body = call_kwargs.kwargs["json"]
76-
assert request_body["query"] == "test query"
77-
assert request_body["api_key"] == "test-key"
78-
assert "include_domains" not in request_body
79-
assert "max_results" not in request_body
71+
tavily_search._client.post = AsyncMock(return_value=mock_tavily_response)
72+
await tavily_search.invoke_tool(
73+
"web_search",
74+
{"query": "test query"},
75+
)
76+
call_kwargs = tavily_search._client.post.call_args
77+
request_body = call_kwargs.kwargs["json"]
78+
assert request_body["query"] == "test query"
79+
assert request_body["api_key"] == "test-key"
80+
assert "include_domains" not in request_body
81+
assert "max_results" not in request_body
8082

8183

8284
async def test_invoke_with_user_location_ignored(tavily_search, mock_tavily_response):
83-
with patch("httpx.AsyncClient.post", new_callable=AsyncMock, return_value=mock_tavily_response) as mock_post:
84-
await tavily_search.invoke_tool(
85-
"web_search",
86-
{
87-
"query": "test query",
88-
"user_location": {"country": "US", "city": "San Francisco"},
89-
},
90-
)
91-
call_kwargs = mock_post.call_args
92-
request_body = call_kwargs.kwargs["json"]
93-
assert "user_location" not in request_body
94-
assert "country" not in request_body
95-
assert "location" not in request_body
85+
tavily_search._client.post = AsyncMock(return_value=mock_tavily_response)
86+
await tavily_search.invoke_tool(
87+
"web_search",
88+
{
89+
"query": "test query",
90+
"user_location": {"country": "US", "city": "San Francisco"},
91+
},
92+
)
93+
call_kwargs = tavily_search._client.post.call_args
94+
request_body = call_kwargs.kwargs["json"]
95+
assert "user_location" not in request_body
96+
assert "country" not in request_body
97+
assert "location" not in request_body
9698

9799

98100
async def test_invoke_with_empty_allowed_domains(tavily_search, mock_tavily_response):
99-
with patch("httpx.AsyncClient.post", new_callable=AsyncMock, return_value=mock_tavily_response) as mock_post:
100-
await tavily_search.invoke_tool(
101-
"web_search",
102-
{
103-
"query": "test query",
104-
"allowed_domains": [],
105-
},
106-
)
107-
call_kwargs = mock_post.call_args
108-
request_body = call_kwargs.kwargs["json"]
109-
assert "include_domains" not in request_body
101+
tavily_search._client.post = AsyncMock(return_value=mock_tavily_response)
102+
await tavily_search.invoke_tool(
103+
"web_search",
104+
{
105+
"query": "test query",
106+
"allowed_domains": [],
107+
},
108+
)
109+
call_kwargs = tavily_search._client.post.call_args
110+
request_body = call_kwargs.kwargs["json"]
111+
assert "include_domains" not in request_body
110112

111113

112114
async def test_invoke_returns_source_metadata(tavily_search, mock_tavily_response):
113115
"""Test that invoke_tool returns source URLs in metadata."""
114-
with patch("httpx.AsyncClient.post", new_callable=AsyncMock, return_value=mock_tavily_response):
115-
result = await tavily_search.invoke_tool(tool_name="web_search", kwargs={"query": "test query"})
116-
assert result.metadata is not None
117-
assert "sources" in result.metadata
118-
assert len(result.metadata["sources"]) == 1
119-
assert result.metadata["sources"][0]["url"] == "https://example.com"
120-
assert result.metadata["query"] == "test query"
116+
tavily_search._client.post = AsyncMock(return_value=mock_tavily_response)
117+
result = await tavily_search.invoke_tool(tool_name="web_search", kwargs={"query": "test query"})
118+
assert result.metadata is not None
119+
assert "sources" in result.metadata
120+
assert len(result.metadata["sources"]) == 1
121+
assert result.metadata["sources"][0]["url"] == "https://example.com"
122+
assert result.metadata["query"] == "test query"

0 commit comments

Comments
 (0)