Skip to content

unconsistent behavior between uvicorn and pytest #501

@ticapix

Description

@ticapix

Hello,

In a server.py, I have a simple health check

# in server.py

from datetime import datetime, timezone
from blacksheep import Application, get, ok

app = Application()

@get("/health")
async def health():
    return ok(f"{datetime.now(timezone.utc).isoformat()}")

and reusing the TestClient from https://www.neoteroi.dev/blacksheep/testing/#using-the-testclient-with-pytest, I have a simple test

# in test_api.py

import pytest
from blacksheep.testing import TestClient

@pytest.mark.asyncio(scope="session")
async def test_health_check(test_client: TestClient) -> None:
    response = await test_client.get("/health")
    assert response is not None
    assert response.status is 200
    print(response.headers)
    assert response.has_header(b'content-type')

Bug

When running with pytest -sv, I'm getting an error because response.headers is empty.

$ PYTHONPATH=. pytest -sv
============================= test session starts ==============================
platform linux -- Python 3.11.2, pytest-8.2.2, pluggy-1.5.0 -- /home/debian/workspace/cde/cde-global/applications/ontology-server/.direnv/python-3.11.2/bin/python3
cachedir: .pytest_cache
rootdir: /home/debian/workspace/cde/cde-global/applications/ontology-server
plugins: asyncio-0.23.7
asyncio: mode=Mode.STRICT
collected 1 item

tests/test_api.py::test_health_check <Headers []>
FAILED

=================================== FAILURES ===================================
______________________________ test_health_check _______________________________

test_client = <blacksheep.testing.client.TestClient object at 0x7f2d176763d0>

    @pytest.mark.asyncio(scope="session")
    async def test_health_check(test_client: TestClient) -> None:
        response = await test_client.get("/health")
        assert response is not None
        assert response.status is 200
        print(response.headers)
>       assert response.has_header(b'content-type')
E       AssertionError: assert False
E        +  where False = <bound method Message.has_header of <Response 200>>(b'content-type')
E        +    where <bound method Message.has_header of <Response 200>> = <Response 200>.has_header

tests/test_api.py:13: AssertionError
=========================== short test summary info ============================
FAILED tests/test_api.py::test_health_check - AssertionError: assert False
============================== 1 failed in 0.04s ===============================

Expected

However, when I run the server with uvicorn server:app and I try with wget, I do get a content-type header.

$ wget -qS -O - http://127.0.0.1:8000/health
  HTTP/1.1 200 OK
  date: Sun, 23 Jun 2024 21:11:01 GMT
  server: uvicorn
  content-type: text/plain; charset=utf-8
  content-length: 32
2024-06-23T21:11:02.151666+00:00

Has anyone an idea of the component/code adding this header after I return my response object and not present when testing ?

Thank you,
Pierre

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions