【问题标题】:how to mock session in Python's request library?如何在 Python 的请求库中模拟会话?
【发布时间】:2018-03-06 09:58:05
【问题描述】:

我一直试图弄清楚如何准确地模拟 Python 请求库的会话,但直到现在才找到解决方案。这是我需要编写测试的 common.py 代码:

import requests

def request_url(method, url):
    return _request_url(method, url)

def _request_url(method, url):
    session = requests.session()
    adapter = TlsAdapter(ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1)
    session.mount("https://", adapter)
    return session.request(method, url)

【问题讨论】:

    标签: python unit-testing testing mocking python-requests


    【解决方案1】:

    只需模拟整个_request_url 函数,而不用打扰会话对象。该函数所做的只是提供一个响应对象,模拟该函数并返回一个模拟响应对象

    但是,如果您正在测试_request_url 函数本身,那么只需模拟session 名称;额外的调用将全部传递给模拟。然后,您可以为 mocked.return_value.rquest.return_value 对象提供您选择的响应对象。

    所以

    from unittest import mock
    
    with mock.patch('requests.session') as mock_session:
        session_instance = mock_session.return_value
        mock_response = session_instance.request.return_value
    
        response = _request_url('METHOD', 'some url')
    
        assert response is mock_response
        session_instance.mount.assert_called()
        session_instance.request.assert_called_with('METHOD', 'some url')
    

    或在TestCase 方法中:

    @mock.patch('requests.session')
    def test_request_url(self,  mock_session):
        session_instance = mock_session.return_value
        mock_response = session_instance.request.return_value
    
        response = _request_url('METHOD', 'some url')
    
        self.assertTrue(response is mock_response)
        session_instance.mount.assert_called()
        session_instance.request.assert_called_with('METHOD', 'some url')
    

    演示:

    >>> from unittest import mock
    >>> import requests, ssl
    >>> class TlsAdapter:
    ...     # mocked adapter, just for illustration purposes
    ...     def __init__(self, *args, **kwargs): pass
    ...
    >>> def _request_url(method, url):
    ...     session = requests.session()
    ...     adapter = TlsAdapter(ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1)
    ...     session.mount("https://", adapter)
    ...     return session.request(method, url)
    ...
    >>> with mock.patch('requests.session') as mock_session:
    ...     session_instance = mock_session.return_value
    ...     mock_response = session_instance.request.return_value
    ...     response = _request_url('METHOD', 'some url')
    ...     assert response is mock_response
    ...     session_instance.mount.assert_called()
    ...     session_instance.request.assert_called_with('METHOD', 'some url')
    ...
    >>> # nothing happened, because the test passed, no assertion errors were raised
    ...
    

    【讨论】:

    • @HussainAliAkbar:没有要修补的“会话”,不,因为没有这样的模块。使用全名,所以requests.session
    • 感谢@MartijnPieters 的详细回答!我会试试这个,看看它是否适合我。
    • 一个后续问题,如果我想添加副作用而不是正常的返回值,例如重定向 302 而不是 200,那么我该怎么做?我知道我必须以某种方式设置 mock_session.side_effect 值,但我似乎无法弄清楚如何做到这一点。可以在这里回答还是我需要问另一个问题?谢谢!
    • 我继续问另一个问题:stackoverflow.com/questions/49148452/…
    • 我的一天才刚刚开始,我会在那里回答。
    猜你喜欢
    • 2013-06-20
    • 2020-06-06
    • 2011-01-11
    • 2013-04-22
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多