FastAPI TestClient测试报错:无法解析Postgres主机名
问题原因
当你在本地直接运行测试脚本时,宿主机无法识别Docker Compose自定义网络里的postgres服务名——这个服务名仅在Docker内部网络中可被解析。而Postman测试是通过容器暴露的端口访问API,API运行在容器内,能正常解析postgres主机,因此测试正常。
解决方案
方案一:本地测试时改用localhost连接数据库
你的Postgres容器已将5432端口映射到宿主机5432端口,本地可通过localhost访问数据库。通过环境变量区分测试与生产环境:
- 在
.env中添加测试专用变量:DATABASE_HOST=postgres TEST_DATABASE_HOST=localhost - 修改数据库连接代码,根据环境选择主机:
import os from sqlalchemy import create_engine if os.getenv("TESTING") == "True": db_host = os.getenv("TEST_DATABASE_HOST", "localhost") else: db_host = os.getenv("DATABASE_HOST", "postgres") DATABASE_URL = f"postgresql://{os.getenv('POSTGRES_USER')}:{os.getenv('POSTGRES_PASSWORD')}@{db_host}:5432/{os.getenv('POSTGRES_DB')}" engine = create_engine(DATABASE_URL) - 运行测试时临时设置环境变量:
TESTING=True pytest tests/
方案二:在Docker容器内运行测试
让测试在API容器中执行,此时测试代码与API处于同一Docker网络,可正常解析postgres服务名:
docker-compose run api pytest tests/
现有卷挂载配置会同步本地代码修改到容器,测试将使用最新代码。
方案三:使用独立测试数据库(推荐)
为测试配置轻量的SQLite数据库,摆脱对Postgres容器的依赖,让测试更独立高效:
- 配置测试专用数据库连接:
from sqlalchemy import create_engine TEST_DATABASE_URL = "sqlite:///./test.db" test_engine = create_engine(TEST_DATABASE_URL, connect_args={"check_same_thread": False}) - 编写测试夹具,实现测试前后的表创建与清理:
import pytest from sqlalchemy.orm import sessionmaker from app.database import Base @pytest.fixture(scope="module") def db_session(): Base.metadata.create_all(bind=test_engine) TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=test_engine) db = TestingSessionLocal() try: yield db finally: db.close() Base.metadata.drop_all(bind=test_engine) - 修改测试代码,使用该测试数据库会话(适配API的数据库依赖逻辑)。
内容的提问来源于stack exchange,提问作者AntonioMoreno
相关产品推荐
相关产品推荐

