b.py:
from unittest.mock import patch
def hello():
print("hello")
return 1
@patch("b.hello", return_value="wow")
def fun(mock_hello):
print(hello())
print("start")
fun()
print("end")
我使用python3:
pie@pie:~$ python3 --version
Python 3.6.9
对于上述代码,我希望得到下一个,因为我嘲笑了hello
:
start
wow
end
但实际上,我是下一个:
pie@pie:~$ python3 b.py
start
start
wow
end
hello
1
end
我对模拟行为完全感到困惑,发生了什么事?
答案 0 :(得分:0)
如果有兴趣的人更新答案,则根本原因是patch target
和patch
在同一文件中。如果不在同一文件中,则不会有任何问题。
从patch function
中unittest/mock.py
的源代码中,我们实际上可以看到它使用__import__
来导入目标:
patch
-> getter, attribute = _get_target(target)
-> getter = lambda: _importer(target)
-> thing = __import__(import_path)
因此上述代码如下:
b.py
启动时,它首先打印start
fun()
,此时patch
将使用__import__
来导入b.hello
。因此b.py
现在充当了一个再次执行的python模块。作为python模块,它输出start
。fun
,因为已经导入了模块,因此不会启动其他导入。在运行模块时,hello()
的实际含义是已经修补的b.hello()
,它应该返回wow
。因此,wow
现在可以打印了。end
。b.py
作为顶级脚本继续运行hello()
,但是现在patch
确实已修补b.hello
,而不是hello
,因此它仍会打印hello
和1
。end
。