如何用测试函数中的任意函数替换方法(不使用 patch.object)?

How to replace a method with an arbitrary function inside test function (not using patch.object)?

我的尝试是在具有预定义值的函数内模拟数据库操作。

我修补了我的 mongo 集合实例的 find 方法并将字典列表设置为演示 return 值(find return 或多或少在类似的数据结构中)。但问题是,find returns 有一个 count() 方法,它没有参数,而我设置的 return 值(list ) 也有一个 count() 方法,但它需要一个参数,而且它的用途也不同。

因此,我的目标是更改 count() 的行为,使其 return 成为我硬编码的列表的 len。 (find方法的return值的len

下面是代码:

在some_module.py、

def somefunc():
    items = mongo_collection.find({"some_field": True}).batch_size(50)

    if items.count() > 0:
        counter += 1

测试中_some_module.py,

@patch.object(some_module, 'mongo_collection')
def test_some_func(patched_collection):
    patched_collection.find.return_value.batch_size.return_value = \
                                              [{'id': 1}, {'id': 2}]
    patched_collection.find.return_value.batch_size.return_value.count = ?

不清楚你要测试什么。

如果出于某种原因你想要类似列表的 "response" 并且它应该作为响应(即,有 count 方法),你应该创建这样的对象并将其设置为 return值。

现在设置[{'id': 1}, {'id': 2}]。一旦你通过 mongo_collection.find().batch_size() return 这个列表,结果实际上是一个列表,而不是模拟。所以,没有更多的东西像 .count = ... 可用。

因此,有以下方法:

  1. 测试响应主体和您在不同测试中的计数,以不同方式修补连接器
  2. 创建更好的响应模拟,即

    class Response(list):
        def count(self):
            return len(self)
    ...
    patched_collection.find.return_value.batch_size.return_value = Response([{'id': 1}, {'id': 2}])
    
  3. 根据模拟库的响应创建响应模拟实例