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

如何Mock父类方法实现子类Mongo旧数据清理逻辑的单元测试

解决方案

1. 核心逻辑说明

你通过装饰器拿到的connect_mock、date_mock本身就是MagicMock对象,不需要替换对象本身,直接给它们的return_value属性赋值为你想要的自定义返回值即可。另外注意装饰器的参数顺序是从下到上和装饰器顺序对应,你之前写的参数顺序是反的,这也是常见的出错点。

2. 完整测试代码示例

import mongomock
from datetime import datetime
from unittest import mock
# 导入你自己实现的子类
from your_module import YourSubClass

@mock.patch("path_to_base_class.BaseClass.connect_to_collection")
@mock.patch("path_to_base_class.BaseClass.get_date_from_input")
def test_remove_old_docs(date_mock, connect_mock):
    # 设置从HDFS读取日期的返回值为指定datetime
    test_date = datetime(2020, 1, 1)
    date_mock.return_value = test_date

    # 构造mongomock内存集合,插入测试数据
    mocked_collection = mongomock.MongoClient().db.collection
    mocked_collection.insert_many([
        {'_id': '1', 'time': datetime(2010, 10, 10, 10, 10, 10)},
        {'_id': '2', 'time': datetime(2015, 10, 10, 10, 10, 10)},
        {'_id': '3', 'time': datetime(2020, 10, 10, 10, 10, 10)},
        {'_id': '4', 'time': datetime(2030, 10, 10, 10, 10, 10)},
        {'_id': '5', 'time': datetime(2040, 10, 10, 10, 10, 10)},
    ])
    # 设置Mongo连接方法的返回值为这个内存集合
    connect_mock.return_value = mocked_collection

    # 实例化子类,执行业务方法
    sub_obj = YourSubClass()
    sub_obj.remove_old_sources()

    # 验证执行结果,示例中早于2020-01-01的2条数据应该被删除
    assert mocked_collection.count_documents({}) == 3
    # 可选:验证方法调用参数是否符合预期
    date_mock.assert_called_once()
    connect_mock.assert_called_once_with("你的数据库名", "你的集合名")

3. 上下文管理器写法(更稳妥,避免路径写错)

如果你不想用装饰器写法,也可以直接patch子类继承的方法,代码如下:

def test_remove_old_docs():
    test_date = datetime(2020, 1, 1)
    mocked_collection = mongomock.MongoClient().db.collection
    # 插入测试数据的逻辑和上面一致,此处省略
    
    with mock.patch.object(YourSubClass, "get_date_from_input", return_value=test_date):
        with mock.patch.object(YourSubClass, "connect_to_collection", return_value=mocked_collection):
            sub_obj = YourSubClass()
            sub_obj.remove_old_sources()
            # 断言逻辑和上面一致

常见问题排查

  • 如果发现mock不生效,大概率是patch路径写错了,遵循patch实际调用位置的原则:如果你的子类在a.b.c模块中导入继承父类,就patcha.b.c.BaseClass.方法名,不要用父类原始定义的模块路径。
  • delete_stale_documents不需要额外mock,它接收mongomock的集合对象后会直接在内存中执行删除逻辑,刚好可以验证你的删除逻辑是否正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 07:30:01