[英]Is it possible to `mock.patch` functions run in multiprocessing (using `spawn`)?
[英]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_local
, test_mock
和test_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.