Skip to content

Commit e80f9ff

Browse files
author
VRTXOmega
committed
test: cover external-exit-stack and session-stack teardown branches
Lines 151, 164, 170-171 were uncovered after stripping stale pragmas: - 151 (__aenter__ with external exit stack) - 164-171 (__aexit__ with external exit stack + session stack teardown) Add two anyio tests: one for the external-exit-stack case verifying the group doesn't touch the caller's stack, and one that populates _session_exit_stacks to exercise the sequential aclose loop.
1 parent dd47262 commit e80f9ff

1 file changed

Lines changed: 34 additions & 5 deletions

File tree

tests/client/test_session_group.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -523,8 +523,37 @@ async def test_unreachable_streamable_http_error_is_catchable() -> None:
523523
"Expected to catch a connection error against an unreachable "
524524
"streamable-http server, but no exception was raised."
525525
)
526-
assert not _is_cancel_scope_runtime_error(caught), (
527-
"Regression of #915: connection error against an unreachable "
528-
"streamable-http server was masked by an anyio cancel-scope "
529-
f"RuntimeError. Got: {type(caught).__name__}: {caught}"
530-
)
526+
assert not _is_cancel_scope_runtime_error(caught), (
527+
"Regression of #915: connection error against an unreachable "
528+
"streamable-http server was masked by an anyio cancel-scope "
529+
f"RuntimeError. Got: {type(caught).__name__}: {caught}"
530+
)
531+
532+
533+
@pytest.mark.anyio
534+
async def test_session_group_with_external_exit_stack(
535+
mock_exit_stack: mock.MagicMock,
536+
) -> None:
537+
"""__aenter__/__aexit__ skip stack management when given an external exit stack."""
538+
group = ClientSessionGroup(exit_stack=mock_exit_stack)
539+
540+
async with group:
541+
pass # __aenter__ covered; __aexit__ triggers next
542+
543+
# mock_exit_stack's own __aenter__/aclose should NOT be called by
544+
# ClientSessionGroup — it's the caller's responsibility.
545+
mock_exit_stack.__aenter__.assert_not_called()
546+
mock_exit_stack.aclose.assert_not_called()
547+
548+
549+
@pytest.mark.anyio
550+
async def test_session_group_teardown_closes_session_stacks() -> None:
551+
"""__aexit__ closes every session-level exit stack sequentially."""
552+
session = mock.MagicMock(spec=mcp.ClientSession)
553+
session_stack = mock.MagicMock(spec=contextlib.AsyncExitStack)
554+
555+
async with ClientSessionGroup() as group:
556+
group._session_exit_stacks[session] = session_stack
557+
558+
session_stack.aclose.assert_awaited_once()
559+

0 commit comments

Comments
 (0)