如何为Sanic+Tortoise配置pytest并搭建内存SQLite测试数据库
Sanic + Tortoise ORM + 内存SQLite 测试配置示例
依赖安装
先安装所需依赖:
pip install sanic tortoise-orm pytest pytest-asyncio sanic-testing
项目结构
sanic_tortoise_test/ ├── app.py └── test_app.py
主应用代码(app.py)
from sanic import Sanic, json from tortoise import fields from tortoise.models import Model from tortoise.contrib.sanic import register_tortoise # 定义数据模型 class User(Model): id = fields.IntField(pk=True) name = fields.CharField(max_length=50) email = fields.CharField(max_length=100, unique=True) class Meta: table = "users" # 初始化Sanic应用 app = Sanic("user_crud") # 注册CRUD路由 @app.post("/users") async def create_user(request): data = request.json user = await User.create(**data) return json({"id": user.id, "name": user.name, "email": user.email}, status=201) @app.get("/users/<user_id:int>") async def get_user(request, user_id): user = await User.get_or_none(id=user_id) if not user: return json({"error": "User not found"}, status=404) return json({"id": user.id, "name": user.name, "email": user.email}) @app.delete("/users/<user_id:int>") async def delete_user(request, user_id): deleted_count = await User.filter(id=user_id).delete() if deleted_count == 0: return json({"error": "User not found"}, status=404) return json({"message": "User deleted successfully"}, status=200) # 生产环境Tortoise配置(测试时会被覆盖) register_tortoise( app, db_url="sqlite://db.sqlite3", modules={"models": ["app"]}, generate_schemas=True, )
测试代码(test_app.py)
import pytest from sanic_testing import TestManager from tortoise.contrib.test import finalizer, initializer from app import app, User # 测试数据库配置 TEST_DB_CONFIG = { "connections": { "default": "sqlite:///:memory:" }, "apps": { "models": { "models": ["app"], "default_connection": "default", } } } @pytest.fixture(scope="module") def test_app(): # 初始化测试客户端管理器 TestManager(app) # 启动Tortoise测试数据库,自动生成表结构 initializer(["app"], db_url=TEST_DB_CONFIG["connections"]["default"]) yield app # 测试模块结束后清理数据库连接 finalizer() @pytest.fixture async def client(test_app): return test_app.test_client # CRUD测试用例 async def test_create_user(client): resp = await client.post("/users", json={"name": "Test User", "email": "test@example.com"}) assert resp.status == 201 data = await resp.json() assert data["name"] == "Test User" assert data["email"] == "test@example.com" async def test_get_user(client): # 先创建测试用户 user = await User.create(name="Get Test", email="get@example.com") resp = await client.get(f"/users/{user.id}") assert resp.status == 200 data = await resp.json() assert data["id"] == user.id assert data["name"] == "Get Test" async def test_get_nonexistent_user(client): resp = await client.get("/users/999") assert resp.status == 404 data = await resp.json() assert data["error"] == "User not found" async def test_delete_user(client): user = await User.create(name="Delete Test", email="delete@example.com") resp = await client.delete(f"/users/{user.id}") assert resp.status == 200 data = await resp.json() assert data["message"] == "User deleted successfully" # 验证用户已被删除 deleted_user = await User.get_or_none(id=user.id) assert deleted_user is None async def test_delete_nonexistent_user(client): resp = await client.delete("/users/999") assert resp.status == 404 data = await resp.json() assert data["error"] == "User not found"
运行测试
在项目根目录执行:
pytest test_app.py -v
关键说明
- 内存SQLite数据库
sqlite:///:memory:会在测试模块启动时创建,模块结束后自动销毁,完全隔离测试数据 - 借助
tortoise.contrib.test的initializer和finalizer自动处理数据库初始化与连接清理,无需手动管理事件循环和连接状态 sanic-testing提供的测试客户端无需启动真实HTTP服务,直接调用应用路由逻辑,提升测试效率- 测试fixture使用
module作用域,确保整个测试模块共享同一数据库实例,避免重复初始化开销
内容的提问来源于stack exchange,提问作者Maksim Burtsev
相关产品推荐
相关产品推荐

