@@ -42,16 +42,60 @@ def _setup_agent_framework_mock():
4242 """
4343 Set up mock for agent_framework which is not a pip-installable package.
4444 This framework is used for Azure AI Agents and needs proper mocking.
45+ Uses ModuleType with real stub classes for names used in type annotations
46+ or as base classes, and MagicMock for everything else.
4547 """
4648 if 'agent_framework' not in sys .modules :
47- # Use MagicMock so any attribute access (ChatAgent, ChatMessage, etc.) works
48- mock_af = MagicMock ()
49-
49+ # Top-level: agent_framework
50+ mock_af = ModuleType ('agent_framework' )
51+
52+ # Names used as base classes or in Union type hints MUST be real classes
53+ # to avoid SyntaxError from typing module's forward reference evaluation.
54+ _class_names = [
55+ 'AgentResponse' , 'AgentResponseUpdate' , 'AgentRunUpdateEvent' ,
56+ 'AgentThread' , 'BaseAgent' , 'ChatAgent' , 'ChatMessage' ,
57+ 'ChatOptions' , 'Content' , 'ExecutorCompletedEvent' ,
58+ 'GroupChatRequestSentEvent' , 'GroupChatResponseReceivedEvent' ,
59+ 'HostedCodeInterpreterTool' , 'HostedMCPTool' ,
60+ 'InMemoryCheckpointStorage' , 'MCPStreamableHTTPTool' ,
61+ 'MagenticBuilder' , 'MagenticOrchestratorEvent' ,
62+ 'MagenticProgressLedger' , 'Role' , 'UsageDetails' ,
63+ 'WorkflowOutputEvent' ,
64+ ]
65+ for name in _class_names :
66+ setattr (mock_af , name , type (name , (), {}))
67+
68+ # Sub-module: agent_framework.azure
69+ mock_af_azure = ModuleType ('agent_framework.azure' )
70+ mock_af_azure .AzureOpenAIChatClient = type ('AzureOpenAIChatClient' , (), {})
71+ mock_af .azure = mock_af_azure
72+
73+ # Sub-module: agent_framework._workflows._magentic
74+ mock_af_workflows = ModuleType ('agent_framework._workflows' )
75+ mock_af_magentic = ModuleType ('agent_framework._workflows._magentic' )
76+ for name in [
77+ 'MagenticContext' , 'StandardMagenticManager' ,
78+ ]:
79+ setattr (mock_af_magentic , name , type (name , (), {}))
80+ for name in [
81+ 'ORCHESTRATOR_FINAL_ANSWER_PROMPT' ,
82+ 'ORCHESTRATOR_PROGRESS_LEDGER_PROMPT' ,
83+ 'ORCHESTRATOR_TASK_LEDGER_PLAN_PROMPT' ,
84+ 'ORCHESTRATOR_TASK_LEDGER_PLAN_UPDATE_PROMPT' ,
85+ ]:
86+ setattr (mock_af_magentic , name , "mock_prompt_string" )
87+ mock_af_workflows ._magentic = mock_af_magentic
88+ mock_af ._workflows = mock_af_workflows
89+
5090 sys .modules ['agent_framework' ] = mock_af
51- sys .modules ['agent_framework.azure' ] = mock_af .azure
52-
91+ sys .modules ['agent_framework.azure' ] = mock_af_azure
92+ sys .modules ['agent_framework._workflows' ] = mock_af_workflows
93+ sys .modules ['agent_framework._workflows._magentic' ] = mock_af_magentic
94+
5395 if 'agent_framework_azure_ai' not in sys .modules :
54- sys .modules ['agent_framework_azure_ai' ] = MagicMock ()
96+ mock_af_ai = ModuleType ('agent_framework_azure_ai' )
97+ mock_af_ai .AzureAIClient = type ('AzureAIClient' , (), {})
98+ sys .modules ['agent_framework_azure_ai' ] = mock_af_ai
5599
56100
57101def _setup_azure_monitor_mock ():
@@ -62,10 +106,33 @@ def _setup_azure_monitor_mock():
62106 sys .modules ['azure.monitor.opentelemetry' ] = mock_module
63107
64108
109+ def _patch_azure_ai_projects_models ():
110+ """
111+ Patch azure.ai.projects.models to add names that may be missing
112+ in older SDK versions (e.g. PromptAgentDefinition).
113+ """
114+ try :
115+ import azure .ai .projects .models as models_mod
116+ missing_names = [
117+ 'PromptAgentDefinition' ,
118+ 'AzureAISearchAgentTool' ,
119+ 'AzureAISearchToolResource' ,
120+ 'AISearchIndexResource' ,
121+ ]
122+ for name in missing_names :
123+ if not hasattr (models_mod , name ):
124+ setattr (models_mod , name , MagicMock ())
125+ except ImportError :
126+ # azure-ai-projects not installed at all — create full mock
127+ sys .modules ['azure.ai.projects' ] = MagicMock ()
128+ sys .modules ['azure.ai.projects.models' ] = MagicMock ()
129+
130+
65131# Set up environment and minimal mocks before any test imports
66132_setup_environment_variables ()
67133_setup_agent_framework_mock ()
68134_setup_azure_monitor_mock ()
135+ _patch_azure_ai_projects_models ()
69136
70137
71138@pytest .fixture
0 commit comments