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

时间:2018-02-01 11:14:28

标签: python python-unittest python-mock

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

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

所以,我的目标是改变count()的行为,以便它返回我硬编码的列表的len。 (len方法的返回值的find

以下是代码:

在some_module.py中,

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

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

在test_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 = ?

1 个答案:

答案 0 :(得分:1)

目前还不清楚你想测试什么。

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

现在您设置[{'id': 1}, {'id': 2}]。一旦通过mongo_collection.find().batch_size()返回此列表,结果实际上是一个列表,而不是模拟。所以,没有像.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. 创建响应模拟作为模拟库响应的实例