簡體   English   中英

mock.patch 和多處理

[英]mock.patch and multiprocessing


我正在努力在多處理環境中使用mock.patch ,而沒有 multiprocessing mock.patch工作正常。 文件名: test_mp.py

import multiprocessing
import mock

def inner():
    return sub()

def sub():
    return "abc"

def test_local():
    assert inner()=="abc"

def test_mp():    
    with multiprocessing.Pool() as pool:
        assert pool.apply(inner,args=[])=='abc'

def test_mock():    
    with mock.patch('test_mp.sub', return_value='xxx') as xx:
        assert inner()=="xxx"
        xx.assert_called_once()

def test_mp_mock():    
    with multiprocessing.Pool() as pool:
        with mock.patch('test_mp.sub', return_value='xyz') as xx:
            assert pool.apply(inner,args=[])=='xyz'
            xx.assert_called_once()

  • 測試test_localtest_mocktest_mock成功完成
  • 但是test_mp_mock失敗了
=================================== FAILURES ===================================
_________________________________ test_mp_mock _________________________________

    def test_mp_mock():
        with multiprocessing.Pool() as pool:
            with mock.patch('test_mp.sub', return_value='xyz') as xx:
>               assert pool.apply(inner,args=[])=='xyz'
E               AssertionError: assert 'abc' == 'xyz'
E                 - abc
E                 + xyz

projects/mfhealth/test_mp.py:25: AssertionError

更新:

基於https://medium.com/ukey/how-mock-patch-decorator-works-in-python-37acd8b78ae並借助sharedmock https://github.com/elritsch/python-sharedmock我能夠進一步,但仍不完整。

我將test_mp.py擴展為

from sharedmock.mock import SharedMock

def inner2(sm):
    with mock.patch('test_mp.sub', sm) as xx:
        return inner()


def test_mp_smock():
    with multiprocessing.Pool() as pool:
        sm=SharedMock()
        sm.return_value="xyz"
        with mock.patch('test_mp.sub', sm) as xx:
            assert pool.apply(inner2,args=[sm])=='xyz'
            assert xx.call_count == 1

def test_mp_mock2():
    with multiprocessing.Pool() as pool:
        sm=mock.Mock()
        sm.return_value="xyz"
        print(f"before patch {sub}, {locals()}")
        with mock.patch('test_mp.sub', sm) as xx:
            print(f"after patch {sub}")
            assert pool.apply(inner2,args=[sm])=='xyz'
            assert xx.call_count == 1

結果如下:

  • test_mp_smock成功完成。
  • test_mp_mock2失敗, _pickle.PicklingError: Can't pickle <class 'mock.mock.Mock'>: it's not the same object as mock.mock.Mock

test_mp_smock的主要缺點是必須引入一個新方法inner2來通過mock.patch激活補丁。 關於如何在不引入包裝方法inner2的情況下將補丁從test_mp_smock傳播到被測代碼的任何想法,因為我無法覆蓋。

pool.apply(inner,args=[])

最后,我讓它工作了。

SharedMock不像Mock那樣靈活,例如。 缺少assert_called_once_with ,...,但您可以設置返回值或檢查調用次數或其 arguments。

import multiprocessing
import mock
from sharedmock.mock import SharedMock


def inner():
    return sub(x="xxx")

def sub(x=""):
    return f"abc"

def fun_under_test():
    with multiprocessing.Pool() as pool:
        assert pool.apply(inner,args=[])=='xyz'

def test_final():
    sm=SharedMock()
    sm.return_value="xyz"
    with mock.patch('test_mp.sub', sm) as xx:
        fun_under_test()
        assert xx.call_count == 1 #number of calls of sub function
        assert xx.mock_calls[0][2]['x']=="xxx" # value of parameters ie sub(x="xxx")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM