[英]Pass parameter to side_effect function for patching in unittest.mock
[英]Is it possible to assign a side_effect to a class member variable in python when patching using the unittest module?
是否可以修补类实例变量并强制它在每次引用时返回不同的值? 具体来说,我有兴趣使用side_effect参数执行此操作
from unittest.mock import patch
def run_test():
myClass = MyClass()
for i in range(2):
print(myClass.member_variable)
class MyClass():
def __init__(self):
self.member_variable = None
@patch('test_me.MyClass.member_variable',side_effect=[1,2], create=True)
def test_stuff(my_mock):
run_test()
assert False
-------------- Captured stdout call ---------------------------------------------------------------------------------------------------------------------
None
None
-------------- Captured stdout call ---------------------------------------------------------------------------------------------------------------------
1
2
side_effect
可以是函数、可迭代对象或异常( https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.side_effect )。 我认为这就是它不起作用的原因。
另一种测试方法是:
>>> class Class:
... member_variable = None
...
>>> with patch('__main__.Class') as MockClass:
... instance = MockClass.return_value
... instance.member_variable = 'foo'
... assert Class() is instance
... assert Class().member_variable == 'foo'
...
这是文档: https : //docs.python.org/3/library/unittest.mock.html#unittest.mock.patch
在您设置的示例的情况下,我无法按照我的想法进行更改,您可能在本课程中有更多项目,并且这个想法可以帮助您。
不是对属性产生副作用的最佳选择,但它可以按我的需要工作。
PS:我最终将让我回答您的问题的代码作为示例。
例子:
# -*- coding: utf-8 -*-
# !/usr/bin/env python3
import requests
from src.metaclasses.singleton import Singleton
from src.services.logger import new_logger
from src.exceptions.too_many_retries import TooManyRetries
from src.exceptions.unavailable_url import UnavailableURL
LOG = new_logger(__name__)
class PostbackService(metaclass=Singleton):
def __init__(self):
self.session = requests.session()
def make_request(self, method, url, headers, data=None, retry=0):
r = self.session.request(method, url, data=data, headers=headers)
if r.status_code != 200:
if retry < 3:
return self.make_request(method, url, headers, data, retry + 1)
message = f"Error performing request for url: {url}"
LOG.error(message)
raise TooManyRetries(message)
return r.json()
测试:
# -*- coding: utf-8 -*-
# !/usr/bin/env python3
from unittest import TestCase
from unittest.mock import patch, MagicMock
from src.services.postback import PostbackService
from src.exceptions.too_many_retries import TooManyRetries
from src.exceptions.unavailable_url import UnavailableURL
class TestPostbackService(TestCase):
@patch("src.services.postback.requests")
def setUp(self, mock_requests) -> None:
mock_requests.return_value = MagicMock()
self.pb = PostbackService()
def test_make_request(self):
self.pb.session.request.return_value = MagicMock()
url = "http://mock.io"
header = {"mock-header": "mock"}
data = {"mock-data": "mock"}
mock_json = {"mock-json": "mock"}
def _def_mock(value):
"""
Returns a MagicMock with the status code changed for each request, so you can test the retry behavior of the application.
"""
mock = MagicMock()
mock.status_code = value
mock.json.return_value = mock_json
return mock
self.pb.session.request.side_effect = [
_def_mock(403),
_def_mock(404),
_def_mock(200),
]
self.assertEqual(self.pb.make_request("GET", url, header, data), mock_json)
self.pb.session.request.side_effect = [
_def_mock(403),
_def_mock(404),
_def_mock(404),
_def_mock(404),
]
with self.assertRaises(TooManyRetries):
self.pb.make_request("GET", url, header, data)
如您所见,我通过将每个的副作用更改为我想要做的来重新创建 magicmock。 它不是漂亮的代码和超级 pythonic,但它按预期工作。 我使用@rsarai 从unittest 文档发送的链接作为创建这个magicmock 对象的基础。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.