如何用Pytest测试FastAPI的异常场景?
问题分析
你用pytest.raises(Exception)抓不到异常是因为TestClient是HTTP客户端,FastAPI会自动把路由里的HTTPException转换成标准的HTTP响应返回,不会把Python异常抛给客户端。所以你的测试代码里,client.post("/")不会抛出异常,而是返回一个状态码400的响应对象。
无需修改API路由的测试方案
直接测试响应的状态码和内容即可,这也是测试HTTP API的标准方式,不需要改动原有路由:
def test_function_exception(): response = client.post("/") assert response.status_code == 400 assert response.json()["detail"] == "failed to do something"
这样既验证了异常场景下的HTTP响应,也能覆盖路由里的try-except逻辑(只要do_something确实抛出了异常)。
若要直接捕获路由内的异常(提升覆盖率验证)
如果想直接验证路由函数内部是否正确抛出了HTTPException(比如为了确保try-except分支确实被触发),可以直接调用路由函数,而不是通过TestClient,同时用pytest.raises捕获HTTPException:
首先在测试中mockdo_something让它抛出异常:
from unittest.mock import patch from fastapi import HTTPException def test_function_internal_exception(): # mock do_something 使其抛出异常 with patch("your_module.do_something") as mock_do: mock_do.side_effect = Exception("test error") # 直接调用路由函数 with pytest.raises(HTTPException) as exc_info: my_function() # 验证异常的状态码和消息 assert exc_info.value.status_code == 400 assert exc_info.value.detail == "failed to do something"
这种方式不需要修改原有路由,只是通过mock和直接调用函数的方式,验证内部的异常处理逻辑,进一步提升代码覆盖率。
总结
- 无需修改路由:通过TestClient测试HTTP响应的状态码和内容,这是API测试的常规做法。
- 验证内部逻辑:mock依赖函数后直接调用路由函数,用
pytest.raises捕获HTTPException,确保异常处理分支被正确执行。
内容的提问来源于stack exchange,提问作者zscrub
相关产品推荐
相关产品推荐

