mock介绍
当一个功能依赖另一个功能时,而这个功能还没有完善,需要使用mock来模拟依赖的返回
mock主要有以下几个库:
- unittest.mock:python内置的用于mock的库,有Mock,MagicMock,path等类可以使用
- pytest-mock: 第三方插件库
- monkeypatch:pytest内置的fixture,也可以提供mock功能
- mockito:第三方库
where to mock
要使用mock,首先得明白mock的原理,在哪个地方mock
以unittest.mock来举例:
使用Mock()或者MagicMock()会生成一个Mock或者MagicMock对象,当调用时,就会返回mock的值。如下:
from unittest.mock import Mock,MagicMock
f=Mock(return_value=34)
print(f()) #34
print(f) #<Mock id='140295868166688'>
Mock(return_value=34),初始化生成一个Mock对象,这个对象在内存中有一个地址,地址是以140开头的
f=Mock(return_value=34),将这个地址赋值给了f,此时,f的地址就是Mock id=‘140295868166688’
当调用f()时就会返回Mock对象的值
所以猜测,Mock是通过将Mock对象的地址赋值给要调用的函数或者方法的地址,改变返回值
所以问题是:在哪里mock?
在方法调用的模块或者查找的模块mock
The key is to patch out SomeClass where it is used (or where it is looked up).
比如:
#mian1.py:
def add(x,y):
result=x+y
Log.info("result:{}".format(result))
return result
#mian4.py中调用add,但是导入的方式不同,先看from XXX import XXX
from LearnPytest.task.main1 import add
def my_add_four(x,y):
result=add(x,y)
return result
#在test_mymock_one.py中测试my_add_four函数,以下两种mock方式
def test_my_mock():
main4.add=Mock(return_value=567)
result=my_add_four(4,5)
print(result)
def test_my_mock_one():
main1.add=Mock(return_value=900)
result = my_add_four(4, 5)
print(result)
if __name__ == '__main__':
pytest.main(["-v","-s","test_mymock_one.py::test_my_mock"])
test_my_mock这种方式的mock起作用,先分析这种mock方式:
首先生成了一个mock对象,return_value在mock调用时才会返回
运行完main4.add=Mock(return_value=567),这里的main4.add已经被替换为mock对象了,需要运行到main4.py时看add的地址