"""MockProvider tests — determinism, JSON mode, failure modes.""" import pytest from ai_service.llm.mock import MockProvider from ai_service.llm.types import Message MSGS = [Message(role="user", content="hello there")] async def test_stream_is_deterministic(): p1, p2 = MockProvider(), MockProvider() out1 = [t async for t in p1.stream_chat(MSGS, model="m")] out2 = [t async for t in p2.stream_chat(MSGS, model="m")] assert "".join(out1) == "".join(out2) assert out1 == out2 async def test_stream_content_differs_for_different_input(): p = MockProvider() a = "".join([t async for t in p.stream_chat(MSGS, model="m")]) b = "".join( [t async for t in p.stream_chat([Message(role="user", content="other")], model="m")] ) assert a != b async def test_json_object_response_format(): import json p = MockProvider() out = "".join( [ t async for t in p.stream_chat( MSGS, model="m", response_format={"type": "json_object"} ) ] ) assert json.loads(out) == {"summary": "mock structured reply", "confidence": 0.87} async def test_fail_before_first_token(): p = MockProvider() p.fail_before_first_token = True with pytest.raises(RuntimeError): async for _ in p.stream_chat(MSGS, model="m"): pass async def test_fail_mid_stream(): p = MockProvider() p.fail_mid_stream_at_index = 2 tokens = [] with pytest.raises(RuntimeError): async for t in p.stream_chat(MSGS, model="m"): tokens.append(t) assert len(tokens) == 2 async def test_cancellation_records_abort(): p = MockProvider() gen = p.stream_chat(MSGS, model="m") await gen.__anext__() await gen.aclose() assert p.abort_recorded is True async def test_chat_returns_full_reply(): p = MockProvider() reply = await p.chat(MSGS, model="m") streamed = "".join([t async for t in p.stream_chat(MSGS, model="m")]) assert reply == streamed