Rodrigo
Rodrigo

Reputation: 321

Mock requests.post

I am using pytest to test a method that calls requests.post. Is there a easy way and preferably without third party libraries to do this?

class Dispatcher:
    def __init__(self, url):
    self.url = url
    self.session = None

    def dispatch(self):
        return self.session.post(self.url).json()


def test_dispatch():
    d = Dispatcher(url="")
    d.session = # ... here, how can I mock the return value of json()?
    result = d.dispatch()

Upvotes: 0

Views: 330

Answers (1)

gold_cy
gold_cy

Reputation: 14216

So this is a pretty straightforward example. We want to set session to be a MagicMock object.

from unittest.mock import MagicMock

def test_dispatch():
    expected = {"fizz": "buzz"}
    mock_session = MagicMock()
    mock_session.configure_mock(
        **{
            "post.return_value": mock_session,
            "json.return_value": expected
        }
    )

    d = Dispatcher(url="")
    d.session = mock_session
    result = d.dispatch()

    assert result == expected

Since Mock objects return a brand new mock object when methods are called on them (without being configured), we have to configure the object as such. If we didn't configure post to return the original mock we have, then it would return a brand new mock object and our test would fail. Conversely you can configure another Mock object to be the return value of post and configure that object, but I prefer this approach.

Explanation showing the call is listed below.

self.session is our mock_session object we created

self.session.post(arg, **kwargs) returns mock_session

mock_session.json() returns the dictionary we specified

Upvotes: 1

Related Questions