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

单元测试时SQLite报json_contains_path不存在错误,但Postman调用正常

原因分析

核心问题是生产/运行环境与单元测试环境的数据库对JSON函数的支持不匹配:

  • Postman调用时,Web应用连接的是支持json_contains_path函数的数据库(比如PostgreSQL、MySQL 8.0+,或者版本≥3.38.0的SQLite)。
  • 单元测试用的是SQLite 3.32.3,而json_contains_path是SQLite 3.38.0才正式加入的函数,低版本SQLite完全不支持这个语法,所以执行查询时会抛出“no such function”错误。

解决方法

可以从以下几个方向处理:

1. 升级SQLite版本

把单元测试环境的SQLite版本升级到3.38.0或更高,让测试环境支持json_contains_path函数,保持查询逻辑一致。

2. 为SQLite自定义json_contains_path函数

利用SQLite的扩展机制,在单元测试初始化时注册自定义函数模拟json_contains_path的行为,示例代码:

import json
import sqlite3

def json_contains_path(json_str, mode, *paths):
    try:
        data = json.loads(json_str.lower())
        for path in paths:
            # 解析JSON路径,比如"$.applications.tech"
            parts = path.strip('$').split('.')
            current = data
            valid = True
            for part in parts:
                if part not in current:
                    valid = False
                    break
                current = current[part]
            if valid:
                # 匹配到任意路径就返回1(对应mode='one')
                return 1
        return 0
    except Exception:
        return 0

# 在单元测试的数据库初始化环节注册该函数
def setup_test_database():
    conn = sqlite3.connect(':memory:')
    conn.create_function('json_contains_path', -1, json_contains_path)
    # 后续用这个连接初始化SQLAlchemy会话

3. 调整查询逻辑,兼容多数据库

修改查询代码,根据当前使用的数据库类型切换查询方式,利用SQLAlchemy的方言判断:

from sqlalchemy import inspect, or_

def search():
    key = request.args.get("search")
    query = db.session.query(Company)
    base_filters = [
        Company.name.like('%' + key + '%'),
        Company.department.like('%' + key + '%')
    ]
    
    # 获取当前数据库方言
    dialect_name = inspect(db.engine).dialect.name
    json_filter = None
    
    apps = get_applications_from_key(key.lower())
    if dialect_name == 'sqlite' and sqlite3.sqlite_version_info < (3, 38, 0):
        # 低版本SQLite用json_extract判断路径是否存在
        app_filters = []
        for app in apps:
            app_filters.append(func.json_extract(Company.app_config, f'$.applications.{app.lower()}').isnot(None))
        json_filter = or_(*app_filters)
    else:
        # 支持json_contains_path的数据库用原有逻辑
        json_filter = func.json_contains_path(
            func.lower(Company.app_config),
            'one',
            *map(lambda app: f'$.applications.{app.lower()}', apps)
        )
    
    query = query.filter(or_(*base_filters, json_filter))
    return query.all()

4. 单元测试使用与生产一致的数据库

如果条件允许,单元测试直接用生产环境同款数据库(比如PostgreSQL),从根源避免数据库差异导致的兼容性问题。


内容的提问来源于stack exchange,提问作者Gerry Volta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 15:23:13