test(teams): patch adapter's TypingActivityInput binding for test_send_typing

The teams adapter imports TypingActivityInput at module load time:

    try:
        from microsoft_teams.api.activities.typing import TypingActivityInput
    except ImportError:
        TypingActivityInput = None

When the real microsoft_teams package isn't installed (CI runner image
doesn't bundle Microsoft Teams SDK), the import fails and the local
binding stays None — even though the test file's _ensure_teams_mock
fixture registers a MockTypingActivityInput in sys.modules. The
test-time mock-in-sys.modules trick only fixes future imports; a binding
captured before the mock was registered remains stale.

send_typing() calls TypingActivityInput() and the resulting TypeError
('NoneType' object is not callable) is swallowed by `except Exception: pass`,
so self._app.send is never reached and the test's assert_awaited_once
fails with "Awaited 0 times" — invisibly, because the swallowed error
hid the real cause.

Fix: monkey-patch the adapter module's local TypingActivityInput binding
in test_send_typing only — narrowest possible patch since no other test
exercises send_typing. Document the import-time-vs-mock-time gap inline
so a future reader doesn't fall into the same trap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
claude-ceo-assistant 2026-05-08 03:46:57 +00:00 committed by dev-lead
parent ddbb1520c9
commit c8bc7cdab5

View File

@ -397,13 +397,22 @@ class TestTeamsSend:
assert "Network error" in result.error assert "Network error" in result.error
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_send_typing(self): async def test_send_typing(self, monkeypatch):
adapter = TeamsAdapter(_make_config( adapter = TeamsAdapter(_make_config(
client_id="id", client_secret="secret", tenant_id="tenant", client_id="id", client_secret="secret", tenant_id="tenant",
)) ))
mock_app = MagicMock() mock_app = MagicMock()
mock_app.send = AsyncMock() mock_app.send = AsyncMock()
adapter._app = mock_app adapter._app = mock_app
# The adapter module imports TypingActivityInput at load time; if
# the real microsoft_teams package isn'"'"'t installed, that local
# binding is None even though the test fixture registers a mock
# in sys.modules. Force a non-None local binding so the call to
# TypingActivityInput() inside send_typing succeeds and we actually
# reach self._app.send.
class _StubTypingActivityInput:
pass
monkeypatch.setattr(_teams_mod, "TypingActivityInput", _StubTypingActivityInput)
await adapter.send_typing("conv-id") await adapter.send_typing("conv-id")
mock_app.send.assert_awaited_once() mock_app.send.assert_awaited_once()