Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在multiprocessing.Pool中使用函数run中的mock_Python_Python 3.x_Unit Testing_Mocking_Python Multiprocessing - Fatal编程技术网

Python 如何在multiprocessing.Pool中使用函数run中的mock

Python 如何在multiprocessing.Pool中使用函数run中的mock,python,python-3.x,unit-testing,mocking,python-multiprocessing,Python,Python 3.x,Unit Testing,Mocking,Python Multiprocessing,在我的代码中,我使用multiprocessing.Pool并发运行一些代码。简化的代码看起来有点像这样: class Wrapper(): session: Session def __init__(self): self.session = requests.Session() # Session initialization def upload_documents

在我的代码中,我使用multiprocessing.Pool并发运行一些代码。简化的代码看起来有点像这样:

    class Wrapper():
        session: Session       


        def __init__(self):
            self.session = requests.Session()
            # Session initialization


        def upload_documents(docs):
            with Pool(4) as pool:
                upload_file = partial(self.upload_document)
                pool.starmap(upload_file, documents)

                summary = create_summary(documents)

            self.upload_document(summary)


        def upload_document(doc):
            self.post(doc)


        def post(data):
            self.session.post(self.url, data, other_params)
因此,通过HTTP发送文档基本上是并行的。现在我想测试这段代码,但却做不到。这是我的测试:

    @patch.object(Session, 'post')
    def test_study_upload(self, post_mock):
        response_mock = Mock()
        post_mock.return_value = response_mock
        response_mock.ok = True

        with Wrapper() as wrapper:
            wrapper.upload_documents(documents)

        mc = post_mock.mock_calls
在调试中,我可以检查模拟调用。有一个看起来有效,就是上传摘要的那个,还有一堆调用,比如
call.json()
call.\uu len\uu()
call.\uu str\uu()
等等

没有上传文档的电话。当我在
upload\u document
方法中设置断点时,我可以看到它对每个文档调用了一次,它按预期工作。但是,我无法测试它,因为我无法通过模拟来验证此行为。我认为这是因为有许多进程调用同一个mock,但仍然-我如何解决这个问题


我使用Python3.6,这里我将采用的方法是使测试尽可能细化,并模拟其他调用。在这种情况下,您希望模拟
对象,并验证它调用的是您期望的内容,而不是在测试期间实际依赖它来加速子进程。以下是我的想法:

@patch('yourmodule.Pool')
def test_study_upload(self, mock_pool_init):
    mock_pool_instance = mock_pool_init.return_value.__enter__.return_value

    with Wrapper() as wrapper:
        wrapper.upload_documents(documents)

    # To get the upload file arg here, you'll need to either mock the partial call here, 
    # or actually call it and get the return value
    mock_pool_instance.starmap.assert_called_once_with_args(upload_file, documents)
然后,您需要使用现有逻辑并单独测试上载文档功能:

@patch.object(Session, 'post')
def test_upload_file(self, post_mock):
    response_mock = Mock()
    post_mock.return_value = response_mock
    response_mock.ok = True

    with Wrapper() as wrapper:
        wrapper.upload_document(document)

    mc = post_mock.mock_calls
这使您可以覆盖创建和控制池的函数,以及池实例调用的函数。注意:我没有测试这个,但我会留下一些给你来填补空白,因为它看起来像是你原始问题中实际模块的缩写版本

编辑:

试试这个:

def test_study_upload(self):
    def call_direct(func_var, documents):
        return func_var(documents)

    with patch('yourmodule.Pool.starmap', new=call_direct)
        with Wrapper() as wrapper:
            wrapper.upload_documents(documents)

这是对starmap调用的修补,以便它直接调用您传入的函数。它完全绕过游泳池;底线是,您不能真正深入到由多处理创建的子流程中。

谢谢,看起来这是唯一的方法。然而,失去集成测试让我感到悲哀。我认为它更像是:如果您正在测试您的池已经处理的函数,并且您正在测试处理向池中添加任务的函数,那么您就完全被覆盖了!也许有另一种方法,只需修补星图。我将用建议编辑我的问题@阿莫菲斯