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

Python中如何为MySQL查询类无确定返回值函数编写结构化unittest测试

针对MySQL查询函数的unittest测试方案

一、先修正现有代码的结构问题

你当前的代码混淆了业务逻辑和测试逻辑,需要先把查询商品的业务函数单独抽离,不要写在unittest的测试类中:

# 单独存放业务逻辑的文件比如product_dao.py
def get_all_products(input=None):
    connection = get_sql_connection()
    cursor = connection.cursor()
    if input:
        # 注意这里原来的写法有SQL注入风险,建议用参数化查询
        query = "SELECT * FROM `online-store`.product WHERE name like %s;"
        cursor.execute(query, (f"%{input}%",))
    else:
        query = "SELECT * FROM `online-store`.product;"
        cursor.execute(query)
    response = cursor.fetchall()
    for row in response:
        print(f"Id={row[0]}\tName={row[1]}\tPrice =£{row[2]}\tSupplier={row[4]}")
    cursor.close()
    connection.close()
    return response

注意:你原来的SQL拼接写法存在SQL注入漏洞,上面改成了参数化查询的正确写法。

二、单元测试的实现思路

测试数据库操作类函数时,必须保证测试环境的数据是可控的,所以需要提前在测试库中插入固定的测试数据,再运行断言判断返回结果是否符合预期。

三、完整的测试代码示例

import unittest
from product_dao import get_all_products
# 你自己的测试库连接方法,不要用生产库做测试
from your_db_config import get_test_sql_connection

class TestProductQuery(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        # 所有测试用例运行前执行一次:初始化测试库、插入测试数据
        cls.conn = get_test_sql_connection()
        cursor = cls.conn.cursor()
        # 清空测试表,插入3条固定测试数据
        cursor.execute("TRUNCATE TABLE `online-store`.product;")
        test_products = [
            (1, "苹果手机", 5999, "128G", "苹果供应商"),
            (2, "华为手机", 4999, "256G", "华为供应商"),
            (3, "苹果耳机", 1299, "无线", "苹果供应商")
        ]
        cursor.executemany(
            "INSERT INTO `online-store`.product (id, name, price, spec, supplier) VALUES (%s, %s, %s, %s, %s)",
            test_products
        )
        cls.conn.commit()
        cursor.close()

    @classmethod
    def tearDownClass(cls):
        # 所有测试用例运行完后执行:清空测试表、关闭连接
        cursor = cls.conn.cursor()
        cursor.execute("TRUNCATE TABLE `online-store`.product;")
        cls.conn.commit()
        cursor.close()
        cls.conn.close()

    def test_get_all_products_no_input(self):
        # 测试无搜索参数的场景:应该返回全部3条数据
        result = get_all_products()
        self.assertEqual(len(result), 3)
        # 校验第一条数据的名称和价格是否符合测试数据
        self.assertEqual(result[0][1], "苹果手机")
        self.assertEqual(result[0][2], 5999)

    def test_get_all_products_with_keyword(self):
        # 测试带搜索关键词的场景:搜索“苹果”应该返回2条数据
        result = get_all_products("苹果")
        self.assertEqual(len(result), 2)
        # 校验搜索结果不包含华为手机
        product_names = [row[1] for row in result]
        self.assertNotIn("华为手机", product_names)

if __name__ == '__main__':
    unittest.main()

四、无需连接数据库的Mock测试方案

如果不需要实际连接数据库,只测试函数逻辑正确性,可以用mock替换数据库连接操作,适合纯单元测试场景:

import unittest
from unittest.mock import patch, Mock
from product_dao import get_all_products

class TestProductQueryMock(unittest.TestCase):
    @patch('product_dao.get_sql_connection')
    def test_get_all_products_with_keyword(self, mock_conn):
        # 模拟游标返回的固定结果
        mock_cursor = Mock()
        mock_cursor.fetchall.return_value = [
            (1, "苹果手机", 5999, "128G", "苹果供应商"),
            (3, "苹果耳机", 1299, "无线", "苹果供应商")
        ]
        mock_conn.return_value.cursor.return_value = mock_cursor

        result = get_all_products("苹果")
        # 校验SQL语句是否正确生成
        mock_cursor.execute.assert_called_once_with(
            "SELECT * FROM `online-store`.product WHERE name like %s;",
            ("%苹果%",)
        )
        self.assertEqual(len(result), 2)

if __name__ == '__main__':
    unittest.main()

五、测试结果说明

运行上述代码后,如果所有用例通过,会输出OK;如果有不符合预期的情况,会明确告知哪条用例失败、预期值和实际值的差异,即可作为符合要求的测试证明。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 13:45:02