66
77import pytest
88
9+ import spec_to_agents .tools .bing_search as bing_search_module
10+
11+
12+ @pytest .fixture (autouse = True )
13+ def reset_web_search_agent ():
14+ """Reset the module-level agent ID cache before and after each test."""
15+ # Reset before test
16+ bing_search_module ._web_search_agent_id = None
17+ yield
18+ # Reset after test to prevent state leakage
19+ bing_search_module ._web_search_agent_id = None
20+
921
1022@pytest .mark .asyncio
1123@patch .dict (
@@ -28,9 +40,12 @@ async def test_web_search_success():
2840 ):
2941 # Setup async context manager
3042 mock_client = Mock ()
43+ mock_agent = Mock ()
44+ mock_agent .id = "test-agent-id"
3145 mock_response = Mock ()
3246 mock_response .text = 'Found 2 results for "Microsoft Agent Framework"\n \n 1. Microsoft Agent Framework\n Build intelligent multi-agent systems.\n URL: https://github.com/microsoft/agent-framework' # noqa: E501
3347
48+ mock_client .create_agent .return_value = mock_agent
3449 mock_client .run = AsyncMock (return_value = mock_response )
3550 mock_client .__aenter__ = AsyncMock (return_value = mock_client )
3651 mock_client .__aexit__ = AsyncMock (return_value = None )
@@ -62,9 +77,12 @@ async def test_web_search_no_results():
6277 patch ("spec_to_agents.tools.bing_search.HostedWebSearchTool" ),
6378 ):
6479 mock_client = Mock ()
80+ mock_agent = Mock ()
81+ mock_agent .id = "test-agent-id"
6582 mock_response = Mock ()
6683 mock_response .text = "No results found for query: xyzabc123nonexistent"
6784
85+ mock_client .create_agent .return_value = mock_agent
6886 mock_client .run = AsyncMock (return_value = mock_response )
6987 mock_client .__aenter__ = AsyncMock (return_value = mock_client )
7088 mock_client .__aexit__ = AsyncMock (return_value = None )
@@ -94,9 +112,12 @@ async def test_web_search_with_custom_count():
94112 patch ("spec_to_agents.tools.bing_search.HostedWebSearchTool" ),
95113 ):
96114 mock_client = Mock ()
115+ mock_agent = Mock ()
116+ mock_agent .id = "test-agent-id"
97117 mock_response = Mock ()
98118 mock_response .text = "Found 2 results"
99119
120+ mock_client .create_agent .return_value = mock_agent
100121 mock_client .run = AsyncMock (return_value = mock_response )
101122 mock_client .__aenter__ = AsyncMock (return_value = mock_client )
102123 mock_client .__aexit__ = AsyncMock (return_value = None )
@@ -118,22 +139,27 @@ async def test_web_search_with_custom_count():
118139 clear = False ,
119140)
120141async def test_web_search_api_error ():
121- """Test web search handles API errors gracefully."""
142+ """Test web_search handles API errors gracefully."""
122143 from spec_to_agents .tools .bing_search import web_search
123144
124145 with (
125146 patch ("spec_to_agents.tools.bing_search.create_agent_client" ) as mock_client_factory ,
126147 patch ("spec_to_agents.tools.bing_search.HostedWebSearchTool" ),
127148 ):
128149 mock_client = Mock ()
129- mock_client .__aenter__ = AsyncMock (side_effect = Exception ("API rate limit exceeded" ))
150+ mock_agent = Mock ()
151+ mock_agent .id = "test-agent-id"
152+ # Make client.run() raise an exception (not agent.run())
153+ mock_client .run = AsyncMock (side_effect = Exception ("API rate limit exceeded" ))
154+ mock_client .create_agent .return_value = mock_agent
155+ # Mock context manager
156+ mock_client .__aenter__ = AsyncMock (return_value = mock_client )
130157 mock_client .__aexit__ = AsyncMock (return_value = None )
131158 mock_client_factory .return_value = mock_client
132159
133160 result = await web_search ("test query" )
134161
135162 assert "Error performing web search" in result
136- assert "Exception" in result
137163 assert "API rate limit exceeded" in result
138164
139165
@@ -156,6 +182,8 @@ async def test_web_search_formatting():
156182 patch ("spec_to_agents.tools.bing_search.HostedWebSearchTool" ),
157183 ):
158184 mock_client = Mock ()
185+ mock_agent = Mock ()
186+ mock_agent .id = "test-agent-id"
159187 mock_response = Mock ()
160188 mock_response .text = (
161189 'Found 1 results for "test"\n \n '
@@ -165,6 +193,7 @@ async def test_web_search_formatting():
165193 " Source: example.com/test"
166194 )
167195
196+ mock_client .create_agent .return_value = mock_agent
168197 mock_client .run = AsyncMock (return_value = mock_response )
169198 mock_client .__aenter__ = AsyncMock (return_value = mock_client )
170199 mock_client .__aexit__ = AsyncMock (return_value = None )
@@ -198,9 +227,12 @@ async def test_web_search_empty_results_list():
198227 patch ("spec_to_agents.tools.bing_search.HostedWebSearchTool" ),
199228 ):
200229 mock_client = Mock ()
230+ mock_agent = Mock ()
231+ mock_agent .id = "test-agent-id"
201232 mock_response = Mock ()
202233 mock_response .text = "No results found for query: empty query"
203234
235+ mock_client .create_agent .return_value = mock_agent
204236 mock_client .run = AsyncMock (return_value = mock_response )
205237 mock_client .__aenter__ = AsyncMock (return_value = mock_client )
206238 mock_client .__aexit__ = AsyncMock (return_value = None )
@@ -230,6 +262,8 @@ async def test_web_search_result_numbering():
230262 patch ("spec_to_agents.tools.bing_search.HostedWebSearchTool" ),
231263 ):
232264 mock_client = Mock ()
265+ mock_agent = Mock ()
266+ mock_agent .id = "test-agent-id"
233267 mock_response = Mock ()
234268 mock_response .text = (
235269 'Found 2 results for "test"\n \n '
@@ -239,6 +273,7 @@ async def test_web_search_result_numbering():
239273 " Second result snippet."
240274 )
241275
276+ mock_client .create_agent .return_value = mock_agent
242277 mock_client .run = AsyncMock (return_value = mock_response )
243278 mock_client .__aenter__ = AsyncMock (return_value = mock_client )
244279 mock_client .__aexit__ = AsyncMock (return_value = None )
@@ -265,13 +300,10 @@ async def test_web_search_result_numbering():
265300)
266301async def test_web_search_agent_persistence ():
267302 """Test that agent ID is stored and agent is retrieved by ID on subsequent calls."""
268- import spec_to_agents .tools .bing_search as bing_search_module
269-
270- # Reset module state
271- bing_search_module ._web_search_agent_id = None
272-
273303 from spec_to_agents .tools .bing_search import web_search
274304
305+ # Note: autouse fixture automatically resets _web_search_agent_id before this test
306+
275307 with (
276308 patch ("spec_to_agents.tools.bing_search.create_agent_client" ) as mock_client_factory ,
277309 patch ("spec_to_agents.tools.bing_search.HostedWebSearchTool" ),
@@ -294,15 +326,19 @@ async def test_web_search_agent_persistence():
294326 mock_create_client .__aenter__ = AsyncMock (return_value = mock_create_client )
295327 mock_create_client .__aexit__ = AsyncMock (return_value = None )
296328
297- # Second client retrieves agent by ID
329+ # Second client retrieves agent by ID and runs queries
298330 mock_retrieve_client .run = AsyncMock (side_effect = [response1 , response2 ])
299331 mock_retrieve_client .__aenter__ = AsyncMock (return_value = mock_retrieve_client )
300332 mock_retrieve_client .__aexit__ = AsyncMock (return_value = None )
301333
302- # Return create client for first call (no agent_id), retrieve client for subsequent calls
303- mock_client_factory .side_effect = lambda agent_id = None : (
304- mock_create_client if agent_id is None else mock_retrieve_client
305- )
334+ # Track calls to verify correct parameters
335+ calls = []
336+
337+ def mock_factory (agent_id = None ):
338+ calls .append (agent_id )
339+ return mock_create_client if agent_id is None else mock_retrieve_client
340+
341+ mock_client_factory .side_effect = mock_factory
306342
307343 # First call - should create agent and store ID
308344 result1 = await web_search ("query 1" )
@@ -316,11 +352,10 @@ async def test_web_search_agent_persistence():
316352 assert bing_search_module ._web_search_agent_id == "test-agent-123"
317353
318354 # Verify create_agent_client was called with correct parameters
319- calls = mock_client_factory .call_args_list
320355 assert len (calls ) == 3 # One for creation, two for retrieval
321- # First call creates (agent_id defaults to None)
322- assert calls [0 ]. kwargs . get ( "agent_id" ) is None
356+ # First call creates (agent_id is None)
357+ assert calls [0 ] is None
323358 # Second call retrieves by ID
324- assert calls [1 ]. kwargs . get ( "agent_id" ) == "test-agent-123"
359+ assert calls [1 ] == "test-agent-123"
325360 # Third call retrieves by ID
326- assert calls [2 ]. kwargs . get ( "agent_id" ) == "test-agent-123"
361+ assert calls [2 ] == "test-agent-123"
0 commit comments