如何在Python的请求库中模拟会话中的副作用?

时间:2018-03-07 09:33:29

标签: python unit-testing mocking python-requests

这是我问yesterday的问题的后续内容。

我正在尝试模拟requests库的会话。虽然我得到了关于如何模拟成功返回值的答案,但我仍在试图弄清楚如何模拟400,401或302等副作用。

这就是我嘲笑会话的方式:

>>> 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')

现在,据我所知,我需要模仿session_instance.request.side_effect。如果我尝试做这样的事情,那就失败了:

    response_redirect = mock.MagicMock()
    response_redirect.status_code = 302
    response_redirect.headers = {"location": "https://absolute"}

    session_instance.request.side_effect = response_redirect
    response = _request_url('METHOD', 'https://absolute')
    self.assertEqual(result, response_redirect)

    #Assertion error

1 个答案:

答案 0 :(得分:1)

你不需要副作用。您的重定向'响应只是session.request调用的另一个返回值。在mock_return参考:

上设置您的属性
mock_response = session_instance.request.return_value
mock_response.status_code = 302
mock_response.headers = {"location": "https://absolute"}

response = _request_url('METHOD', 'http://absolute')

在需要时使用.side_effects

  • 提出例外
  • 处理多个调用(您可以将side_effects设置为要生成的返回值序列,按顺序使用。)
  • 需要访问已传递给调用的值(您可以将side_effect设置为使用相同参数调用的函数。)

但是:如果您要测试的代码是_request_url(),那么如果请求导致重定向,则无关紧要_request_url()中的代码对返回的响应完全无动于衷,那么为什么还需要对其进行测试呢?

另一方面,如果您正在测试使用 _request_url()作为实用程序函数的代码,那么您应该模拟该函数,而不是requests图书馆。