2 changed files with 84 additions and 0 deletions
@ -0,0 +1,44 @@ |
|||
import json |
|||
from collections.abc import AsyncIterable, Iterable |
|||
|
|||
from fastapi import FastAPI |
|||
from fastapi.testclient import TestClient |
|||
from pydantic import BaseModel |
|||
|
|||
|
|||
class Item(BaseModel): |
|||
name: str |
|||
|
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.get("/items/stream-bare-async") |
|||
async def stream_bare_async() -> AsyncIterable: |
|||
yield {"name": "foo"} |
|||
|
|||
|
|||
@app.get("/items/stream-bare-sync") |
|||
def stream_bare_sync() -> Iterable: |
|||
yield {"name": "bar"} |
|||
|
|||
|
|||
client = TestClient(app) |
|||
|
|||
|
|||
def test_stream_bare_async_iterable(): |
|||
"""Test that bare AsyncIterable (no type args) works and streams JSONL.""" |
|||
response = client.get("/items/stream-bare-async") |
|||
assert response.status_code == 200 |
|||
assert response.headers["content-type"] == "application/jsonl" |
|||
lines = [json.loads(line) for line in response.text.strip().splitlines()] |
|||
assert lines == [{"name": "foo"}] |
|||
|
|||
|
|||
def test_stream_bare_sync_iterable(): |
|||
"""Test that bare Iterable (no type args) works and streams JSONL.""" |
|||
response = client.get("/items/stream-bare-sync") |
|||
assert response.status_code == 200 |
|||
assert response.headers["content-type"] == "application/jsonl" |
|||
lines = [json.loads(line) for line in response.text.strip().splitlines()] |
|||
assert lines == [{"name": "bar"}] |
|||
@ -0,0 +1,40 @@ |
|||
from collections.abc import AsyncIterable, Iterable |
|||
|
|||
import pytest |
|||
from fastapi import FastAPI |
|||
from fastapi.exceptions import ResponseValidationError |
|||
from fastapi.testclient import TestClient |
|||
from pydantic import BaseModel |
|||
|
|||
|
|||
class Item(BaseModel): |
|||
name: str |
|||
price: float |
|||
|
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.get("/items/stream-invalid") |
|||
async def stream_items_invalid() -> AsyncIterable[Item]: |
|||
yield {"name": "valid", "price": 1.0} |
|||
yield {"name": "invalid", "price": "not-a-number"} |
|||
|
|||
|
|||
@app.get("/items/stream-invalid-sync") |
|||
def stream_items_invalid_sync() -> Iterable[Item]: |
|||
yield {"name": "valid", "price": 1.0} |
|||
yield {"name": "invalid", "price": "not-a-number"} |
|||
|
|||
|
|||
client = TestClient(app) |
|||
|
|||
|
|||
def test_stream_json_validation_error_async(): |
|||
with pytest.raises(ResponseValidationError): |
|||
client.get("/items/stream-invalid") |
|||
|
|||
|
|||
def test_stream_json_validation_error_sync(): |
|||
with pytest.raises(ResponseValidationError): |
|||
client.get("/items/stream-invalid-sync") |
|||
Loading…
Reference in new issue