¿Cómo afirmar las excepciones HTTP esperadas en FastAPI Pytest?

CorePress2024-01-25  12

Tengo un enrutador simple diseñado para lanzar una excepción HTTP:

@router.get('/404test')
async def test():
    raise HTTPException(HTTP_404_NOT_FOUND, "404 test!")

Quiero afirmar que se lanzó la excepción, según los documentos de FastaAPI:

def test_test():
    response = client.get("/404test")
    assert response.status_code == 404

La excepción se lanza antes de que se evalúe la aserción, marcando la prueba como fallida:

>       raise HTTPException(HTTP_404_NOT_FOUND, "404 test!")
E       fastapi.exceptions.HTTPException: (404, '404 test!')

¿Qué me falta para anticipar adecuadamente las excepciones HTTP en mi prueba?

Parece que agregar un "administrador de contexto" en forma de con pytest.raises(HTTPException) como e:... alrededor de la operación de obtención y luego afirmando como afirmar e.value.status_code == 404, respuesta.textHace el truco. ¿Pero quizás haya una manera más elegante?

- Jakub Strebeyko

28/03/2021 a las 17:11



------------------------------------

Suponiendo que tenemos la siguiente ruta configurada en nuestra aplicación fastapi:

@router.get('/404test')
async def test():
    raise HTTPException(HTTP_404_NOT_FOUND, "404 test!")

Pude hacer que un pytest funcionara con el siguiente fragmento de código:

from fastapi import HTTPException

def test_test():
    with pytest.raises(HTTPException) as err:
        client.get("/404test")
    assert err.value.status_code == 404
    assert err.value.detail == "404 test!"

Parece que el error es el objeto HTTPException real, no la representación json. Cuando detecte este error, podrá realizar afirmaciones sobre ese objeto HTTPException.

Asegúrese de ejecutar las afirmaciones (assert) fuera del bloque de instrucciones with porqueCuando se genera el error, se detiene toda la ejecución dentro del bloque después de la llamada http, por lo que la prueba pasará pero las afirmaciones nunca se evaluarán.

Puede hacer referencia a los detalles, el código de estado y cualquier otro atributo en la excepción con err.value.XXX.



------------------------------------

Quizás puedas hacer esto usando el siguiente código de muestra.

~/Desktop/fastapi_sample  $ cat service.py                                 
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/wrong")
async def wrong_url():
    raise HTTPException(status_code=400, detail="404 test!")

~/Desktop/fastapi_sample $ cat test_service.py                            
from fastapi.testclient import TestClient
from fastapi_sample.service import app
client = TestClient(app)


def test_read_item_bad_token():
    response = client.get("/wrong")
    assert response.status_code == 400
    assert response.json() == {"detail": "404 test!"}%                                                                                                        
    
~/Desktop/fastapi_sample $ pytest                                         
==================================================================== test session starts ====================================
platform darwin -- Python 3.7.9, pytest-6.1.0, py-1.9.0, pluggy-0.13.1
rootdir: /Users/i869007/Desktop/workspace/SAP/cxai/fastapi_postgres_tutorial
collected 1 item

test_service.py .                                                                                                                                      [100%]

===================================================================== 1 passed in 0.78s ======================================

0

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare