Val*_*Val 4 python mocking python-requests python-unittest
我想模拟一个函数requests.Session,该函数使用在上下文管理器中创建的对象来执行请求get,再次使用上下文管理器。所以涉及到两个上下文管理器。
这是一个示例代码:
# main.py
from requests import Session
def fun(session):
with session.get("https://httpstat.us/200") as response:
print(response)
def run():
with Session() as session:
fun(session)
if __name__ == "__main__":
run()
Run Code Online (Sandbox Code Playgroud)
200执行时,会按预期打印的状态代码。
现在我想模拟 get 请求,以返回不同的值。不知怎的,我无法浏览混乱的上下文管理器和返回值。
这是我最大的努力:
# maintest.py
from unittest.mock import patch
from main import run
def test_main():
with patch("main.Session") as mocked_session:
mocked_session.__enter__.return_value.get.__enter__.return_value = "MOCKED"
run()
Run Code Online (Sandbox Code Playgroud)
使用 pytest 运行测试,我希望得到"MOCKED"打印,但我得到了
<MagicMock name='Session().__enter__().get().__enter__()' id='140303100714240'>
__enter__我尝试过任何.get可以想象的组合.return_value
你几乎猜对了,正确的mock方法是:
with patch("main.Session") as mocked_session:
mocked_session.return_value.__enter__.return_value.get.return_value.__enter__.return_value = "MOCKED"
Run Code Online (Sandbox Code Playgroud)
我将对此进行分解以进行澄清。
你session_mock指的是Session班级。要获取Session实例,您可以使用return_value(就像每次调用一样)。
该with语句在内部调用__enter__()该会话来获取实例session,因此您必须__enter__为方法和return_value调用添加内容。
现在您调用get()该对象,按照相同的逻辑,该对象需要添加一个get.return_value.
最后,这在另一个with语句中用于 create response,这又需要添加一个__enter__.return_value.
结果为您提供了response模拟的对象Session,您可以设置另一个值。
如果将其分解为代码,它将类似于:
with patch("main.Session") as mocked_session:
mocked_session_instance = mocked_session.return_value
mocked_session_object = mocked_session_instance.__enter__.return_value
mocked_get = mocked_session_object.get.return_value
mocked_response = mocked_get.__enter__
mocked_response.return_value = "MOCKED"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1930 次 |
| 最近记录: |