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

如何测试Flask中无返回值的数据库新增函数?

问题

我有一个向数据库添加新记录的Flask函数add_report_to_db,该函数无返回值,内部通过try-except捕获异常并使用flash给出提示。当前用unittest测试时,即便函数执行出现异常(比如传入无法转为float的longitude参数),函数仍返回None导致测试通过,请问如何验证函数未抛出任何异常?

函数代码

def add_report_to_db(latitude, longitude, color: str, comment: str):
    """Add a new report to the DB."""
    try:
        report = Report(
            latitude=float(latitude),
            longitude=float(longitude),
            color=color,
            comment=comment,
            ip=request.remote_addr,
        )
        db.session.add(report)
        db.session.commit()
        flash("Success!", category="success")

    except Exception as e:
        flash("Error." + str(e), category="error")

测试代码

class BasicsTestCase(unittest.TestCase):
    """General test cases."""

    def setUp(self):
        """Execute before unit test. Create an app and in memory DB."""
        self.app = create_app("testing")
        self.app_context = self.app.app_context()
        self.app_context.push()
        db.create_all()
        self.current_map = folium.Map(location=(50.45, 30.52))
        self.client = self.app.test_client(use_cookies=True)

        report = Report(
            latitude=50.45,
            longitude=30.52,
            color="red",
            comment="comment",
            ip="127.0.0.1",
        )
        db.session.add(report)
        db.session.commit()

    def tearDown(self):
        """Execute after unit test. Drop DB, session, app."""
        db.session.remove()
        db.drop_all()
        self.app_context.pop()

    def test_add_report_to_db(self):
        """Test add a new report to the DB."""
        with current_app.test_request_context():
            result = add_report_to_db(
                latitude=50.45,
                longitude="testing",  # 故意传入错误参数
                color="red",
                comment="comment",
            )
            self.assertIsNone(result)  # 即使有异常测试也通过
            self.assertRaises(not Exception, result)  # 我需要类似这样的验证逻辑
解决方案

因为函数内部已经用try-except捕获了所有异常,所以它永远不会向外抛出异常,自然没法用assertRaises来检测。要验证函数是否成功执行(即没有触发except分支),可以从以下两个方面入手:

1. 检查Flash消息的内容和分类

函数执行成功时会触发flash("Success!", category="success"),异常时触发flash("Error." + str(e), category="error")。测试时可以通过Flask的get_flashed_messages(with_categories=True)来获取消息,判断是否是成功的那条:

修改测试用例如下:

def test_add_report_to_db_success(self):
    """测试成功添加记录到数据库"""
    with self.app.test_request_context():
        add_report_to_db(
            latitude=50.45,
            longitude=30.53,  # 合法的数值参数
            color="red",
            comment="test comment",
        )
        # 获取带分类的Flash消息
        flashed_messages = get_flashed_messages(with_categories=True)
        # 验证是否存在成功消息
        self.assertIn(("success", "Success!"), flashed_messages)
        # 额外验证数据库记录数是否增加
        self.assertEqual(Report.query.count(), 2)

def test_add_report_to_db_failure(self):
    """测试添加记录失败的场景"""
    with self.app.test_request_context():
        add_report_to_db(
            latitude=50.45,
            longitude="testing",  # 非法参数,触发异常
            color="red",
            comment="test comment",
        )
        flashed_messages = get_flashed_messages(with_categories=True)
        # 验证是否存在错误消息
        self.assertTrue(
            any(category == "error" and msg.startswith("Error.") for category, msg in flashed_messages)
        )
        # 验证数据库记录数未变化
        self.assertEqual(Report.query.count(), 1)

2. 验证数据库状态变化

函数成功执行会向数据库新增一条记录,所以可以查询Report表的总记录数,确认是否比初始值多1条;如果执行失败,记录数应该保持不变。

原测试无效的原因

  • self.assertIsNone(result)永远为真:因为函数没有定义返回值,默认返回None,不管是否触发异常。
  • self.assertRaises(not Exception, result)用法错误:assertRaises需要传入异常类和可调用对象,而不是函数执行后的结果。而且因为函数内部捕获了所有异常,它根本不会向外抛出异常,所以这个断言从逻辑上就不成立。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 18:24:43