@@ -111,22 +111,19 @@ async def test_stdio_connect_success(self):
111111 """Test successful stdio connection."""
112112 client = StdioMCPClient ("echo" , ["test" ])
113113
114- with patch ("subprocess.Popen" ) as mock_popen :
115- mock_process = MagicMock ()
116- mock_process .poll .return_value = None # Process is running
117- mock_popen .return_value = mock_process
114+ with patch ("praisonaiui.features.mcp.stdio_client" ) as mock_stdio_client :
115+ # Mock the context manager
116+ mock_session_manager = AsyncMock ()
117+ mock_session = AsyncMock ()
118+ mock_session_manager .__aenter__ .return_value = mock_session
119+ mock_stdio_client .return_value = mock_session_manager
118120
119121 result = await client .connect ()
120122
121123 assert result is True
122- assert client .process == mock_process
123- mock_popen .assert_called_once_with (
124- ["echo" , "test" ],
125- stdin = ANY ,
126- stdout = ANY ,
127- stderr = ANY ,
128- text = True
129- )
124+ assert client .session == mock_session
125+ mock_stdio_client .assert_called_once ()
126+ mock_session .initialize .assert_called_once ()
130127
131128 @pytest .mark .asyncio
132129 async def test_stdio_connect_failure (self ):
@@ -142,37 +139,58 @@ async def test_stdio_disconnect(self):
142139 """Test stdio disconnect."""
143140 client = StdioMCPClient ("echo" , ["test" ])
144141
145- # Mock process
146- mock_process = MagicMock ()
147- client .process = mock_process
142+ # Mock session and session manager
143+ mock_session = AsyncMock ()
144+ mock_session_manager = AsyncMock ()
145+ client .session = mock_session
146+ client ._session_manager = mock_session_manager
147+ client ._connected = True
148148
149149 await client .disconnect ()
150150
151- mock_process . terminate . assert_called_once ( )
152- mock_process . wait . assert_called_once_with ( timeout = 5 )
151+ mock_session_manager . __aexit__ . assert_called_once_with ( None , None , None )
152+ assert client . session is None
153153 assert client .process is None
154154
155155 @pytest .mark .asyncio
156156 async def test_stdio_disconnect_with_kill (self ):
157- """Test stdio disconnect with force kill ."""
157+ """Test stdio disconnect with exception handling ."""
158158 client = StdioMCPClient ("echo" , ["test" ])
159159
160- # Mock process that doesn't terminate gracefully
161- mock_process = MagicMock ()
162- mock_process .wait .side_effect = [subprocess .TimeoutExpired ("cmd" , 5 ), None ]
163- client .process = mock_process
160+ # Mock session that throws exception during disconnect
161+ mock_session = AsyncMock ()
162+ mock_session_manager = AsyncMock ()
163+ mock_session_manager .__aexit__ .side_effect = Exception ("Disconnect failed" )
164+ client .session = mock_session
165+ client ._session_manager = mock_session_manager
166+ client ._connected = True
164167
165- with patch ( "subprocess.TimeoutExpired" , subprocess . TimeoutExpired ):
166- await client .disconnect ()
168+ # Should not raise exception
169+ await client .disconnect ()
167170
168- mock_process . terminate .assert_called_once ()
169- mock_process . kill . assert_called_once ()
171+ mock_session_manager . __aexit__ .assert_called_once ()
172+ assert client . session is None
170173 assert client .process is None
171174
172175 @pytest .mark .asyncio
173176 async def test_stdio_list_tools (self ):
174177 """Test listing tools from stdio client."""
175178 client = StdioMCPClient ("echo" , ["test" ])
179+
180+ # Mock session with list_tools response
181+ mock_session = AsyncMock ()
182+ mock_tool = MagicMock ()
183+ mock_tool .name = "filesystem_read"
184+ mock_tool .description = "Read file contents"
185+ mock_tool .inputSchema = {"type" : "object" , "properties" : {"path" : {"type" : "string" }}}
186+
187+ mock_result = MagicMock ()
188+ mock_result .tools = [mock_tool ]
189+ mock_session .list_tools .return_value = mock_result
190+
191+ client .session = mock_session
192+ client ._connected = True
193+
176194 tools = await client .list_tools ()
177195
178196 assert len (tools ) == 1
@@ -183,10 +201,21 @@ async def test_stdio_list_tools(self):
183201 async def test_stdio_call_tool (self ):
184202 """Test calling a tool via stdio client."""
185203 client = StdioMCPClient ("echo" , ["test" ])
204+
205+ # Mock session with call_tool response
206+ mock_session = AsyncMock ()
207+ mock_result = MagicMock ()
208+ mock_result .content = [{"type" : "text" , "text" : "Tool executed successfully for test_tool" }]
209+ mock_session .call_tool .return_value = mock_result
210+
211+ client .session = mock_session
212+ client ._connected = True
213+
186214 result = await client .call_tool ("test_tool" , {"arg" : "value" })
187215
188- assert "result" in result
189- assert "test_tool" in result ["result" ]
216+ assert result is not None
217+ assert len (result ) > 0
218+ mock_session .call_tool .assert_called_once_with ("test_tool" , {"arg" : "value" })
190219
191220
192221class TestSSEMCPClient :
0 commit comments