Ric*_*c W 11 python nested mocking
我目前正在努力寻找一种模拟多层/嵌套返回值的好方法.换句话说,我想返回一个魔术模拟,然后返回一个带有它自己的设置返回值的魔术模拟.我发现这相对麻烦,我正在寻找一个更优雅和可维护的解决方案.
我正在尝试有效地测试以下代码.URL返回需要进一步处理的json字符串:
import json
from urllib.request import url open
def load_json():
# first return value
response = urlopen("http://someurl.com/api/getjson")
# in turn, contains two nested return values for read and decode
response_dict = json.loads(response.read().decode('utf-8'))
Run Code Online (Sandbox Code Playgroud)
到目前为止,这就是我嘲笑的方式,这非常不优雅并且使维护变得复杂:
class MyTestCase(TestCase):
@patch('load_json_path.urlopen')
def test_load_json(self, mock_urlopen):
### trying to simplify all of this
# third nested return
mock_decode = MagicMock(return_value='["myjsondata"]')
# second nested return value
mock_response = MagicMock()
mock_response.read.return_value=mock_decode
# first nested return value
mock_urlopen.return_value = mock_response
### trying to simplify all of this
load_json()
Run Code Online (Sandbox Code Playgroud)
最后,我试图模拟的是来自解码函数的返回数据,它来自url open函数.这应该可以在一行中或以更简单的方式使用,也许使用输入方法.理想情况下,mock会在test_load_json函数中看起来像这样:
mock_urlopen.__enter__.loads.__enter__.decode.return_value = '["myjsondata"]'
Run Code Online (Sandbox Code Playgroud)
不幸的是,我似乎无法在模拟文档中找到任何有用的东西.任何帮助赞赏.
Ric*_*c W 23
结果证明这很容易并且有记录.但是,命名并不简单,需要知道自己在寻找什么.引用的模拟是链式调用,实际上是在模拟库中记录的.
在此示例中,mock_urlopen应如下所示:
mock_urlopen.return_value.read.return_value.decode.return_value = '["myjsondata"]'
Run Code Online (Sandbox Code Playgroud)
这很好用.有关更多详细信息,请查看python doc:https://docs.python.org/3/library/unittest.mock-examples.html#mocking-chained-calls
我已经为您提供了这门辅助课程:
from unittest.mock import Mock
class ProxyMock:
"""Put me for easy referral"""
def __init__(self, mock, _first=True):
self._mock_ = mock
self._first_ = _first
def __getattr__(self, name):
if self._first_:
new_mock = getattr(self._mock_, name)
else:
new_mock = getattr(self._mock_.return_value, name)
return ProxyMock(new_mock, _first=False)
def __setattr__(self, name, value):
if name in ("_mock_", "_first_"):
return super().__setattr__(name, value)
setattr(self._mock_, name, value)
a = Mock()
ProxyMock(a).b.c.return_value = 123
assert a.b().c() == 123
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5651 次 |
| 最近记录: |