mock就是测试过程中,对一些不容易获取的数据,创建一个虚拟的对象以便测试,这个虚拟的对象就是Mock对象。一般用于单元测试或自动化测试依赖第三方接口时应用。
init
name
-
return_value
-
side_effect
覆盖return_value,当mock对象被调用时,返回该值,一般是异常返回或者是一个list/tuple ```python
mock_test.py
import requests
def mock_request(url): return requests.get(url=url).status_code
def invoke_mock_request(url): return mock_request(url)
```python
# test_mock_1.py
import pytest
from api_testcases.mock_test import invoke_mock_request, mock_request
def test_mock_init(mocker):
"""patch(target, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)
target:传入当前需要mock的方法(接口),字符串格式
name:mock对象的名称
return_value:mock对象被调用的返回值
side_effect:覆盖return_value,当mock对象被调用时,返回该值,一般是异常返回或者是一个list/tuple
spec:设置mock对象的属性
"""
init_mocker = mocker.patch('api_testcases.mock_test.mock_request', name='test mocker init',
return_vlaue=mock_request)
invoke_mock_request(URL)
init_mocker.assert_called()
side_effect_list = [200]
# 当side_effect被设置的时候,return_value就不起作用了,side_effect被设置为一个异常也可以被指定的参数的值是一个list或者tuple
side_effect_mocker = mocker.patch('api_testcases.mock_test.mock_request', name='test mocker init',
return_vlaue=mock_request, side_effect=side_effect_list)
assert invoke_mock_request(URL) == side_effect_list[0]
side_effect_mocker.assert_called()
if __name__ == "__main__":
pytest.main()
"""
============================= test session starts ==============================
platform darwin -- Python 3.7.7, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /Users/zaygee/pytest_test, configfile: pytest.ini
plugins: allure-pytest-2.9.42, mock-3.6.1, xdist-2.2.1, forked-1.3.0
collected 1 item
test_mock_1.py::test_mock_init PASSED [100%]
============================== 1 passed in 0.02s ===============================
"""
spec
import pytest
class Foo(object): _num = 10
def test_mocker_spec(mocker):
# 指定属性list
spec_list = ['_value', 'callFunc']
mocker_spec = mocker.patch('api_testcases.mock_test.mock_request', spec=spec_list)
logger.info(mocker_spec._value)
# 执行类属性
mocker_class_spec = mocker.patch('api_testcases.mock_test.mock_request', spec=Foo)
logger.info(mocker_class_spec._num)
if name == “main“: pytest.main()
“”” ============================= test session starts ============================== platform darwin — Python 3.7.7, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 rootdir: /Users/zaygee/pytest_test, configfile: pytest.ini plugins: allure-pytest-2.9.42, mock-3.6.1, xdist-2.2.1, forked-1.3.0 collected 1 item
test_mock_1.py::test_mocker_spec
———————————————— live log call ————————————————-
2021-08-29 22:47:02 INFO
============================== 1 passed in 0.02s =============================== “””
<a name="oGUkf"></a>
### 断言
1. **assert_called**:检查mock对象至少被调用一次
1. **assert_not_called**:检查mock对象没有被调用
1. **assert_called_once**:检查mock对象只被调用一次
1. **assert_called_with:**检查mock对象的参数是否正确
1. **assert_called_once_with**:检查mock对象只被调用一次
1. **assert_any_call**:检查mock对象在全局过程中是否调用了该方法
```python
import pytest
from api_testcases.mock_test import invoke_mock_request, mock_request
from common import logger
URL = 'https://docs.cypress.io/'
def test_mock_request(mocker):
mocker_inst = mocker.patch('api_testcases.mock_test.mock_request', return_value=mock_request, name='test mock')
assert invoke_mock_request(URL) == mocker_inst.return_value
# 断言至少被调用一次
mocker_inst.assert_called()
# 断言只被调用一次
mocker_inst.assert_called_once()
# 断言mock对象的参数是否正确
mocker_inst.assert_called_with(URL)
# 断言mock对象是否没有被调用
# mocker_inst.assert_not_called()
mocker_inst.assert_called_once_with(URL)
# 断言对象在全局过程中是否调用了该方法
mocker_inst.assert_any_call(URL)
logger.info(mocker_inst)
if __name__ == "__main__":
pytest.main()
"""
============================= test session starts ==============================
platform darwin -- Python 3.7.7, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /Users/zaygee/pytest_test, configfile: pytest.ini
plugins: allure-pytest-2.9.42, mock-3.6.1, xdist-2.2.1, forked-1.3.0
collected 1 item
test_mock_1.py::test_mock_request
-------------------------------- live log call ---------------------------------
2021-08-29 22:51:22 INFO <MagicMock name='test mock' id='140218070657296'>
PASSED [100%]
============================== 1 passed in 0.01s ===============================
"""
# mock_test.py
import requests
def mock_request(url):
return requests.get(url=url).status_code
def invoke_mock_request(url):
return mock_request(url)
# test_mock_1.py
import mock
import pytest
from mock import Mock
from api_testcases.mock_test import invoke_mock_request, mock_request
def test_mock_request():
with mock.patch('api_testcases.mock_test.mock_request', return_value=200, side_effect=mock_request) as mock_foo:
assert invoke_mock_request(URL) == mock_foo.return_value
@mock.patch('api_testcases.mock_test.mock_request', return_value=300)
def test_mock_request1(mock_request):
assert invoke_mock_request(URL) == mock_request.return_value
if __name__ == "__main__":
pytest.main()
"""
============================= test session starts ==============================
platform darwin -- Python 3.7.7, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /Users/zaygee/pytest_test, configfile: pytest.ini
plugins: allure-pytest-2.9.42, mock-3.6.1, xdist-2.2.1, forked-1.3.0
collected 2 items
test_mock_1.py::test_mock_request PASSED [ 50%]
test_mock_1.py::test_mock_request1 PASSED [100%]
============================== 2 passed in 0.63s ===============================
"""
mock管理方法
- attach_mock:将一个mock对象添加到另一个mock对象中
- configure_mock:修改mock对象的return_value值 ```python import pytest from api_testcases.mock_test import invoke_mock_request, mock_request, TestMock1, TestMock2 from common import logger
def test_mock_management(mocker): mocker_attach_1 = mocker.patch(‘api_testcases.mock_test.TestMock1’) mocker_attach_2 = mocker.patch(‘api_testcases.mock_test.TestMock2’) logger.info(mocker_attach_1._value1) logger.info(mocker_attach_1.func1) logger.info(mocker_attach_2)
# 调用attach_mock方法,将mocker_attach_2 添加到mocker_attach_1中,重命名为mock_attach
mocker_attach_1.attach_mock(mocker_attach_2, 'mock_attach')
logger.info(mocker_attach_1.func1)
logger.info(mocker_attach_1.mock_attach.func2)
# configure_mock方法,修改mock对象的return_value值
mocker_attach_3 = mocker.patch('api_testcases.mock_test.mock_request')
mocker_attach_3.configure_mock(return_value=100)
assert invoke_mock_request(URL) == 100
if name == “main“: pytest.main()
“”” ============================= test session starts ============================== platform darwin — Python 3.7.7, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 rootdir: /Users/zaygee/pytest_test, configfile: pytest.ini plugins: allure-pytest-2.9.42, mock-3.6.1, xdist-2.2.1, forked-1.3.0 collected 1 item
test_mock_1.py::test_mock_management
———————————————— live log call ————————————————-
2021-08-29 23:00:40 INFO
============================== 1 passed in 0.01s =============================== “”” ```