Le modèle de test suggéré nécessite une duplication standard du code de l'application et ne montre pas le test de l'application directement.
https://docs.aiohttp.org/en/stable/testing.html#pytest
Je devrais pouvoir passer mon module d'application directement à test_client
pour tester mon application.
Les documents montrent la construction de l'application à partir de gestionnaires à la volée avant chaque test. Passer le vrai app
directement à test_client
fonctionne bien la première fois, puis échoue avec "RuntimeError: web.Application instance initialized with different loop".
# 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'
J'ai piraté le problème pour l'instant en jetant un coup d'œil au code source et en déterminant la cause de l'erreur.
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
Je ne comprends pas immédiatement pourquoi ce code est nécessaire. Je n'ai trouvé aucun contexte dans l'historique de git. La définition de app._loop = None
dans ma méthode de nettoyage de test semble éviter le problème sans aucun effet secondaire négatif. Ce code est-il vraiment nécessaire ? Ce correctif pourrait-il être intégré dans test_client
?
Application
est un objet avec état, il doit être recréé pour chaque test de la suite de tests unitaires.
La durée de vie de l'application doit être plus courte que celle de la boucle d'événements.
Astuce : remplacez app.app
par async def app.make_app()
coroutine qui renvoie une nouvelle application à chaque appel.
Ajouter def make_app()
à app.py
? Ça a du sens.
La tornade FWIW fait la promotion du motif make_app()
dans son tout premier exemple. Je ne pense pas que se moquer de l'application dans le fichier de test soit un bon modèle à promouvoir pour les documents.
Honnêtement, je ne pense pas que se moquer d'un objet aiohttp
soit un bon modèle
Ce fil a été automatiquement verrouillé car il n'y a eu aucune activité récente après sa fermeture. Veuillez ouvrir un [nouveau numéro] pour les bogues liés.
Si vous pensez que des points importants ont été soulevés dans cette discussion, veuillez inclure ces extraits dans ce [nouveau numéro].
Commentaire le plus utile
Application
est un objet avec état, il doit être recréé pour chaque test de la suite de tests unitaires.La durée de vie de l'application doit être plus courte que celle de la boucle d'événements.
Astuce : remplacez
app.app
parasync def app.make_app()
coroutine qui renvoie une nouvelle application à chaque appel.