Hussain Ali Akbar
Hussain Ali Akbar

Reputation: 1655

How to mock side effects in session in Python's request library?

This is a followup to a question that I asked yesterday.

I am trying to mock a session of the requests library. While I got my answer as to how to mock a successful return value, I am still trying to figure out how to mock side effects such as 400, 401, or 302 etc.

This is how I am mocking a session:

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

Now, as far as I have read, I need to mock session_instance.request.side_effect. If I try to do something like this, it fails:

    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

Upvotes: 2

Views: 4060

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1122382

You don't need a side effect. Your 'redirect' response is just another return value for the session.request call. Set your attributes on the mock_return reference:

mock_response = session_instance.request.return_value
mock_response.status_code = 302
mock_response.headers = {"location": "https://absolute"}

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

Use .side_effects for when you need to:

  • raise exceptions
  • handle multiple calls (you can set side_effects to a sequence of return values to produce, used in order).
  • need to have access to the values that have been passed to the call (you can set side_effect to a function that'll be called with the same arguments).

However: if the code you are testing is _request_url(), then it should not matter if the request resulted in a redirect or not. The code in _request_url() is entirely indifferent to what kind of response is being returned, so why should you need to test for that at all?

If, on the other hand you are testing code that uses _request_url() as a utility function, then you should be mocking that function, and not the requests library.

Upvotes: 3

Related Questions