django-ninja icon indicating copy to clipboard operation
django-ninja copied to clipboard

[BUG] Utilising TestAsyncClient with `await` causes a mypy error

Open anorthall opened this issue 11 months ago • 3 comments

Running the following minimal example:

from ninja.testing import TestAsyncClient
from core.api import api

async def test_async_client_mypy() -> None:
    client = TestAsyncClient(api)
    response = await client.get("/")

Produces the following mypy error:

error: "NinjaResponse" has no attribute "__await__"  [attr-defined]

Am I doing something wrong here - misunderstanding how this is supposed to work - or is this a real bug? Clearly the TestAsyncClient returns a coroutine when being utilised on an Async view, and also clearly no such __await__ method is defined. I would think that either:

  • Documentation needs to be improve to indicate proper usage, or
  • Stubs need to be improved to silence mypy

To be clear, there is no actual functional problem here. The test client works fine in the example above. It is purely that an error is thrown by mypy.

Relevant parts of mypy config:

[mypy]
strict = True
plugins = pydantic.mypy, mypy_django_plugin.main

[mypy.plugins.django-stubs]
django_settings_module = "config.django.settings.local"

[pydantic-mypy]
init_forbid_extra = True
init_typed = True
warn_required_dynamic_aliases = True

Versions

  • python: 3.12.8
  • django: 5.1.4
  • django-ninja: 1.3.0
  • pydantic: 2.10.3
  • mypy: 1.13.0
  • django-stubs: 5.1.1

anorthall avatar Dec 15 '24 06:12 anorthall

I am also encountering this

lucaslcode avatar Jan 31 '25 17:01 lucaslcode

I ran into this issue as well, but with basedpyright instead of mypy. The type checker doesn’t recognize that NinjaResponse is awaitable:

error: "NinjaResponse" is not awaitable
    "NinjaResponse" is incompatible with protocol "Awaitable[_T_co@Awaitable]"
      "__await__" is not present (reportGeneralTypeIssues)

As a workaround I currently need to clutter my async tests with lines like:

    response = await aclient.post("/press-releases/batch/", json=payload)  # pyright: ignore[reportGeneralTypeIssues]
    assert response.status_code == 204

This workaround is fine for now, but it would be great if the client could be made type-safe with respect to async behavior so static analysis tools pick it up correctly.

adonig avatar Apr 17 '25 09:04 adonig

I got a related issue, but not the same, https://github.com/vitalik/django-ninja/issues/1440

tim-hub avatar Apr 24 '25 03:04 tim-hub