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

使用PyTest测试Delete接口遇404:如何摆脱数据库ID依赖?

解决CRUD接口测试中依赖数据库ID的问题

你完全可以不依赖数据库现有ID,让删除、查询测试稳定通过,核心思路有两种:Mock数据库访问层(完全脱离真实数据库),或者使用独立测试数据库+前置数据准备(可控的真实数据交互)。下面分别展开并结合你的代码给出实现方案:

方案一:Mock数据库层,完全脱离真实数据库

这种方式不需要和任何真实数据库交互,通过Mock掉接口里操作数据库的函数/方法,模拟“ID存在”的场景,直接验证接口的逻辑和返回格式。

比如你的删除接口/access-issues/delete/<id>,本质是调用数据库的查询(确认ID存在)和删除操作,你可以Mock这两个数据库操作的返回值,让它们始终返回“成功”。

修改你的测试代码示例:

假设你的接口逻辑里是调用access_issue_service.delete_access_issue(id)这个服务层方法来操作数据库,我们可以Mock这个方法:

@patch('flask_jwt_extended.view_decorators.verify_jwt_in_request')
@patch('your_app.module.access_issue_service.delete_access_issue')  # 替换成实际的数据库操作路径
def test_sites_delete(mock_delete, mock_verify, client):
    # 模拟删除方法返回成功(比如返回True表示删除成功)
    mock_delete.return_value = True
    
    response = client.delete('/access-issues/delete/3')  # 随便用一个ID都可以
    
    assert response.status_code == 200
    assert b'Success: Access Issue Deleted Successfully' in response.data
    # 验证Mock方法被正确调用,传入了对应的ID
    mock_delete.assert_called_once_with('3')

同理,查询单个ID的测试也可以Mock查询方法,返回预设的测试数据:

@patch('flask_jwt_extended.view_decorators.verify_jwt_in_request')
@patch('your_app.module.access_issue_service.get_access_issue_by_id')
def test_access_by_id(mock_get, mock_verify, client):
    # 模拟查询返回预设的访问问题数据
    mock_get.return_value = {
        'id': '3',
        'date_time': '2020-05-21',
        'asset_label': '123456',
        # 其他字段...
    }
    
    response = client.get('/access-issues/get/3')
    
    assert response.status_code == 200
    assert b'Success: Access Issue fetched Successfully' in response.data
    mock_get.assert_called_once_with('3')

方案二:使用独立测试数据库+前置数据准备

如果想测试真实的数据库交互逻辑,可以用一个专门的测试数据库(和生产/开发库隔离),在每个测试前自动创建测试数据,测试后清理。

实现步骤:

  1. 配置测试环境的数据库连接(比如用SQLite内存库,或者专门的测试PostgreSQL库)。
  2. 写一个pytest fixture,在测试前创建一条测试数据,返回其ID;测试后删除该数据或回滚事务。

代码示例:

import json
import pytest
from . import app, db  # 假设你的应用有db实例
from .models import AccessIssue  # 假设你的数据模型是AccessIssue

@pytest.fixture
def client():
    # 配置测试数据库(比如用内存SQLite)
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
    app.config['TESTING'] = True
    
    with app.app_context():
        db.create_all()  # 创建表
        yield app.test_client()
        db.drop_all()  # 测试后清理

@pytest.fixture
def test_access_issue(client):
    # 创建一条测试数据,返回其ID
    issue = AccessIssue(
        date_time='2020-05-21',
        asset_label='123456',
        external_ref='123',
        building_name='Hilton',
        floor='one',
        room='123',
        reason='Cant enter',
        description='description',
        asset_id='1',
        picture_url='http://example.com',
        picture_width=1200
    )
    db.session.add(issue)
    db.session.commit()
    yield issue.id  # 返回测试数据的ID
    # 测试后删除这条数据
    db.session.delete(issue)
    db.session.commit()

@patch('flask_jwt_extended.view_decorators.verify_jwt_in_request')
def test_sites_delete(mock_verify, client, test_access_issue):
    # 使用fixture提供的真实存在的ID
    response = client.delete(f'/access-issues/delete/{test_access_issue}')
    
    assert response.status_code == 200
    assert b'Success: Access Issue Deleted Successfully' in response.data

@patch('flask_jwt_extended.view_decorators.verify_jwt_in_request')
def test_access_by_id(mock_verify, client, test_access_issue):
    response = client.get(f'/access-issues/get/{test_access_issue}')
    
    assert response.status_code == 200
    assert b'Success: Access Issue fetched Successfully' in response.data

两种方案的选择

  • 如果只需要验证接口的HTTP逻辑、返回格式、权限校验,用Mock方案更高效,测试速度快,不依赖外部环境。
  • 如果需要验证数据库操作的正确性(比如删除真的会从库中移除数据),选择测试数据库方案,能覆盖真实的业务流程。

内容的提问来源于stack exchange,提问作者Graham Patrick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 14:47:37