How can I mock requests and the response? How can I mock requests and the response? python python

How can I mock requests and the response?


This is how you can do it (you can run this file as-is):

import requestsimport unittestfrom unittest import mock# This is the class we want to testclass MyGreatClass:    def fetch_json(self, url):        response = requests.get(url)        return response.json()# This method will be used by the mock to replace requests.getdef mocked_requests_get(*args, **kwargs):    class MockResponse:        def __init__(self, json_data, status_code):            self.json_data = json_data            self.status_code = status_code        def json(self):            return self.json_data    if args[0] == 'http://someurl.com/test.json':        return MockResponse({"key1": "value1"}, 200)    elif args[0] == 'http://someotherurl.com/anothertest.json':        return MockResponse({"key2": "value2"}, 200)    return MockResponse(None, 404)# Our test case classclass MyGreatClassTestCase(unittest.TestCase):    # We patch 'requests.get' with our own method. The mock object is passed in to our test case method.    @mock.patch('requests.get', side_effect=mocked_requests_get)    def test_fetch(self, mock_get):        # Assert requests.get calls        mgc = MyGreatClass()        json_data = mgc.fetch_json('http://someurl.com/test.json')        self.assertEqual(json_data, {"key1": "value1"})        json_data = mgc.fetch_json('http://someotherurl.com/anothertest.json')        self.assertEqual(json_data, {"key2": "value2"})        json_data = mgc.fetch_json('http://nonexistenturl.com/cantfindme.json')        self.assertIsNone(json_data)        # We can even assert that our mocked method was called with the right parameters        self.assertIn(mock.call('http://someurl.com/test.json'), mock_get.call_args_list)        self.assertIn(mock.call('http://someotherurl.com/anothertest.json'), mock_get.call_args_list)        self.assertEqual(len(mock_get.call_args_list), 3)if __name__ == '__main__':    unittest.main()

Important Note: If your MyGreatClass class lives in a different package, say my.great.package, you have to mock my.great.package.requests.get instead of just 'request.get'. In that case your test case would look like this:

import unittestfrom unittest import mockfrom my.great.package import MyGreatClass# This method will be used by the mock to replace requests.getdef mocked_requests_get(*args, **kwargs):    # Same as aboveclass MyGreatClassTestCase(unittest.TestCase):    # Now we must patch 'my.great.package.requests.get'    @mock.patch('my.great.package.requests.get', side_effect=mocked_requests_get)    def test_fetch(self, mock_get):        # Same as aboveif __name__ == '__main__':    unittest.main()

Enjoy!


Try using the responses library. Here is an example from their documentation:

import responsesimport requests@responses.activatedef test_simple():    responses.add(responses.GET, 'http://twitter.com/api/1/foobar',                  json={'error': 'not found'}, status=404)    resp = requests.get('http://twitter.com/api/1/foobar')    assert resp.json() == {"error": "not found"}    assert len(responses.calls) == 1    assert responses.calls[0].request.url == 'http://twitter.com/api/1/foobar'    assert responses.calls[0].response.text == '{"error": "not found"}'

It provides quite a nice convenience over setting up all the mocking yourself.

There's also HTTPretty:

It's not specific to requests library, more powerful in some ways though I found it doesn't lend itself so well to inspecting the requests that it intercepted, which responses does quite easily

There's also httmock.


Here is what worked for me:

import mock@mock.patch('requests.get', mock.Mock(side_effect = lambda k:{'aurl': 'a response', 'burl' : 'b response'}.get(k, 'unhandled request %s'%k)))