Das vorgeschlagene Testmuster erfordert eine Boilerplate-Duplizierung des App-Codes und zeigt nicht, dass die App direkt getestet wird.
https://docs.aiohttp.org/en/stable/testing.html#pytest
Ich sollte mein App-Modul direkt an test_client
, um meine App zu testen.
Die Dokumentation zeigt, wie die App vor jedem Test von Handlern im Handumdrehen erstellt wird. Die direkte Übergabe des echten app
an test_client
funktioniert beim ersten Mal einwandfrei, schlägt dann mit "RuntimeError: web.Application instance initialized with different loop" fehl.
# handler.py
async def foo():
return 'foo'
# app.py
from aiohttp import web
from .handler import foo
app = web.Application()
app.add_routes([web.get('/foo/', foo)])
# test.py
from .app import app
async def test_foo_status(test_client):
response = await client.get('/foo/')
assert response.status == 200
async def test_foo_body(test_client):
response = await client.get('/foo/')
body = await response.text()
assert body == 'foo'
Ich habe das Problem vorerst umgangen, indem ich mir den Quellcode angesehen und die Ursache des Fehlers ermittelt habe.
if self._loop is not None and self._loop is not loop:
raise RuntimeError(
"web.Application instance initialized with different loop")
https://github.com/aio-libs/aiohttp/blob/e561eaa/aiohttp/web_app.py#L134
Es ist mir nicht sofort klar, warum dieser Code notwendig ist. Ich konnte keinen Kontext in der Git-Historie finden. Das Festlegen von app._loop = None
in meiner Testbereinigungsmethode scheint das Problem ohne negative Nebenwirkungen zu vermeiden. Ist dieser Code wirklich notwendig? Könnte dieser Fix in test_client
?
Application
ist ein zustandsbehaftetes Objekt, es sollte für jeden Test aus der Unit Test Suite neu erstellt werden.
Die Lebensdauer der Anwendung sollte kürzer sein als die der Ereignisschleife.
Hinweis: Ersetzen Sie app.app
durch die Coroutine async def app.make_app()
die bei jedem Aufruf eine neue App zurückgibt.
def make_app()
zu app.py
hinzufügen? Das macht Sinn.
FWIW Tornado fördert das Muster make_app()
in ihrem allerersten Beispiel. Ich glaube nicht, dass das Verspotten der App in der Testdatei ein gutes Muster für die Förderung von Dokumenten ist.
Ehrlich gesagt denke ich nicht, dass es ein gutes Muster ist, ein aiohttp
Objekt zu verspotten
Dieser Thread wurde automatisch gesperrt, da nach dem Schließen in letzter Zeit keine Aktivität stattgefunden hat. Bitte öffnen Sie eine [neue Ausgabe] für verwandte Fehler.
Wenn Sie das Gefühl haben, dass in dieser Diskussion wichtige Punkte erwähnt werden, nehmen Sie diese Auszüge bitte in diese [neue Ausgabe] auf.
Hilfreichster Kommentar
Application
ist ein zustandsbehaftetes Objekt, es sollte für jeden Test aus der Unit Test Suite neu erstellt werden.Die Lebensdauer der Anwendung sollte kürzer sein als die der Ereignisschleife.
Hinweis: Ersetzen Sie
app.app
durch die Coroutineasync def app.make_app()
die bei jedem Aufruf eine neue App zurückgibt.