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