如何从调用方法的函数中修补参数?

How can i patch out a parameter from a function that calls a method?

您好,我是单元测试的新手,因此 unittest.mock 遇到了一个大问题。 我的项目由不同的模块组成。 我的第一个模块是常规模块:

general.py


def do_something(item, collection): 
    # some more code that i want to test
    try:
        collection.insert_one(item)
    except:
        print("did not work")

我的第二个模块是 my_module.py

mymodule.py

import general
from pymongo import MongoClient

client = MongoClient("localhost", 27017)
db = client['db']
collection = db['col']

item = 
  {
    "id": 1
  }



def method:
    general.do_something(item, collection)

现在我想测试 general.py 中的 do_something(item, collection) 方法,因此我想模拟 collection.insert_one(item)。我没有找到可能的解决方案。 我用补丁试过了,但我的问题是,参数集合(它是一个 pymongo 集合)是一个调用函数的参数。我现在如何设法模拟 collection.insert_one?

我的目标是提取 collection.insert_one 并在其中设置 MagicMock。这个 Magic Mock 应该有可能崩溃以检查 except 部分是否有效,或者不崩溃以检查 try 部分是否有效。

TestGeneral.py
import unnittest

class TestGeneral(unittest.TestCase):

    @patch()
    def test_general():





提前致谢! :)

这里实际上不需要模拟,您可以创建一个具有类似功能的 class。

TestGeneral.py
import unnittest

class TestGeneral(unittest.TestCase):

    def test_general_success():
        assert general.do_something(collection(), None)

    def test_general_failure():
        with self.assertRaises(Exception): 
            general.do_something(collection(fail=True), None))

class collection:
    def __init__(self, fail=False):
        self.fail = fail

    def insert_one(self, item):
        if self.fail:
            raise Exception
        return True

然后您还可以检查标准输出以确保在成功时使用打印

如果您出于某种原因不得不使用 mock,此方法可能有效

TestGeneral.py 导入 unnittest

class TestGeneral(unittest.TestCase):

    @mock.patch('{your path}.my_module.MongoClient')
    def test_general_success(mock_mongo):
        mock_mongo.return_value = {'db': None, 'col': collection()}
        assert general.do_something(None, None)  # None here since the collection is mocked anyway

    @mock.patch('{your path}.my_module.MongoClient')
    def test_general_failure(mock_mongo):
        mock_mongo.return_value = {'db': None, 'col': collection(fail=True)}
        with self.assertRaises(Exception): 
            general.do_something(None, None))

class collection:
    def __init__(self, fail=False):
        self.fail = fail

    def insert_one(self, item):
        if self.fail:
            raise Exception
        return True

这样做的缺点是您现在已经模拟了整个 MongoDB,这意味着它的任何其他用途(即客户端)也将被模拟