python - How can I mock requests and the response?

ID : 10271

viewed : 38

Tags : pythonmockingrequestpython

Top 5 Answer for python - How can I mock requests and the response?

vote vote


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

import requests import unittest from unittest import mock  # This is the class we want to test class MyGreatClass:     def fetch_json(self, url):         response = requests.get(url)         return response.json()  # This method will be used by the mock to replace requests.get def 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] == '':         return MockResponse({"key1": "value1"}, 200)     elif args[0] == '':         return MockResponse({"key2": "value2"}, 200)      return MockResponse(None, 404)  # Our test case class class 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('')         self.assertEqual(json_data, {"key1": "value1"})         json_data = mgc.fetch_json('')         self.assertEqual(json_data, {"key2": "value2"})         json_data = mgc.fetch_json('')         self.assertIsNone(json_data)          # We can even assert that our mocked method was called with the right parameters         self.assertIn(''), mock_get.call_args_list)         self.assertIn(''), 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 unittest from unittest import mock from my.great.package import MyGreatClass  # This method will be used by the mock to replace requests.get def mocked_requests_get(*args, **kwargs):     # Same as above   class 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 above  if __name__ == '__main__':     unittest.main() 


vote vote


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

import responses import requests  @responses.activate def test_simple():     responses.add(responses.GET, '',                   json={'error': 'not found'}, status=404)      resp = requests.get('')      assert resp.json() == {"error": "not found"}      assert len(responses.calls) == 1     assert responses.calls[0].request.url == ''     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.

vote vote


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


I used requests-mock for writing tests for separate module:

# import requests  class A():      def get_response(self, url):         response = requests.get(url)         return response.text 

And the tests:

# import requests_mock import unittest  from module import A   class TestAPI(unittest.TestCase):      @requests_mock.mock()     def test_get_response(self, m):         a = A()         m.get('', text='a response')         self.assertEqual(a.get_response(''), 'a response')         m.get('', text='b response')         self.assertEqual(a.get_response(''), 'b response')         m.get('', text='c response')         self.assertEqual(a.get_response(''), 'c response')  if __name__ == '__main__':     unittest.main() 
vote vote


this is how you mock, change it to your http method

@patch.object(requests, 'post') def your_test_method(self, mockpost):     mockresponse = Mock()     mockpost.return_value = mockresponse     mockresponse.text = 'mock return'      #call your target method now 

Top 3 video Explaining python - How can I mock requests and the response?