【问题标题】:mocking functions from base class来自基类的模拟函数
【发布时间】:2021-08-17 17:23:37
【问题描述】:

我有一个基类,我在其中连接到 mongodb 集合并从 hdfs 文件中读取日期值,然后删除与从此 hdfs 文件中读取的值相比更旧的值。我在单元测试方面遇到了一些问题,所以:

在子类中,我有以下内容:

def remove_old_sources(self):
    input_date = self.get_date_from_input()
    mongo_collection = self.connect_to_collection(db, collection)
    deleted_files_count = self.delete_stale_documents(mongo_collection, input_date)

上面调用的所有函数都来自基类。我的问题是如何通过以下方式模拟它们:

带有datetime 对象的input_date 和带有Collection 的mongo_collection 来自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)},
])

如果我理解正确的话,这个mongomock 在内存中创建了一个本地 mongodb。

我试过了:

@mock.patch("path_to_base_class.get_date_from_input")
@mock.patch("path_to_base_class.connect_to_collection")
def test_remove_old_docs(connect_mock, date_mock)

然后初始化子类并运行remove_old_sources 但模拟对象是MagicMock 这样的对象,我不确定如何用上面提到的内容覆盖它们。还尝试使用上下文管理器with mock.patch(BaseClass, "function_name", mocked_stuff),然后初始化Child 类,但它不能像这样工作。

非常感谢您对此的任何帮助!

【问题讨论】:

    标签: python unit-testing testing mocking


    【解决方案1】:

    您会得到MagicMock 对象,因为这是您调用模拟对象时产生的标准对象类型。如果您想要传递其他内容,您可以随时替换他们的 return_value 属性。

    但是,您不需要模拟您的 mongo 集合,您的代码无论如何都不会触及任何数据。

    您的代码进行了 3 次调用:

        input_date = self.get_date_from_input()
        mongo_collection = self.connect_to_collection(db, collection)
        deleted_files_count = self.delete_stale_documents(mongo_collection, input_date)
    

    从前两次调用开始,代码设置了两个局部变量 input_datemongo_collection,然后将它们传递给第三个方法 self.delete_stale_documents()

    如果您的目标是验证代码是否正确地将这两个参数传递给第三个方法,那么您所要做的就是模拟出这三个方法并验证前两个的返回值是否传递给第三个方法:

    @mock.patch("path_to_base_class.delete_stale_documents")
    @mock.patch("path_to_base_class.connect_to_collection")
    @mock.patch("path_to_base_class.get_date_from_input")
    def test_remove_old_docs(date_mock, connect_mock, delete_mock):
        input_date_mock = date_mock.return_value  # a specific MagicMock object
        collection_mock = connect_mock.return_value  # another specific MagicMock object
    
        # call code-under-test here
    
        delete_mock.assert_called_with(collection_mock, input_date_mock)
    

    只有当connect_mock()date_mock() 调用的结果用于调用delete_mock() 时,delete_mock.assert_called_with() 才会通过。

    如果您的测试涉及更多,例如返回值self.delete_stale_documents(),您可以通过在测试前设置.return_value 来设置特定值作为该调用的返回值:

        delete_mock.return_value = 42
    

    现在,deleted_files_count 将设置为 42,如果您的代码正确处理了该值,您可以进行进一步的断言。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-16
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多