You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 08:03:19