title: Mocking an API request for downstream module using Python
body: <p>I am a beginner when it comes to writing tests and mocking.</p>
  
  <p>I have a created two modules. One module object (Site) creates another object from my second module (Item) on init. The Item object makes a call to an API endpoint to get some data using <code>requests</code>.</p>
  
  <p>I want to Mock the API call I am making so I can test things like a bad response and importantly have control over the response data.</p>
  
  <p>I have simplified my code and put below. When I run the test I get back the actual response data and not what I have mocked.</p>
  
  <p>I have a feeling I am not putting my Mock in the right place. Also, I have seen lots of people saying to use @unittest.patch annotation. I am not clear if I should be using that here.</p>
  
  <p>So I am looking for how to get <code>_get_range_detail</code> to actually return a Mocked response from <code>requests</code> and also just general feedback on if it looks like I am approaching this the right way.</p>
  
  <pre><code># hello_world.py
  
  from mymodule.site import Site
  
  sites = [
      dict(
          name="site1",
          ranges=[
              "range1",
              "range2"
          ]
      )
  ]
  
  
  site_object = Site(sites[0]['name'], sites[0]['ranges'])
  for i in site_object.get_ranges_objects():
      print(i.range_detail)
  </code></pre>
  
  <pre><code># site.py
  
  from mymodule.item import Item
  
  class Site:
  
      def __init__(self, name, ranges):
  
          self.name = name
          self.ranges = ranges
          self.ranges_objects = []
          for my_range in ranges:
              self.ranges_objects.append(Item(my_range))
  
      def get_ranges_objects(self):
  
          return self.ranges_objects
  </code></pre>
  
  <pre><code># item.py
  
  import requests
  
  class Item:
  
      def __init__(self, range_name):
  
          self.range_name = range_name
          self.range_detail = self._get_range_detail(self.range_name)
  
      def _get_range_detail(self, range_name):
  
          uri = "https://postman-echo.com/get?some_cool_value=real_value"
          try:
              r = requests.get(uri)
              if r.status_code == 200:
                  return r.json()['args']
              else:
                  return None
          except Exception as e:
              print(e)
              exit(1)
  </code></pre>
  
  <pre><code># test_site.py
  
  import pytest
  from mymodule.site import Site
  from unittest import mock
  from mymodule.item import requests
  
  def test_get_ranges_objects():
  
      sites = [
          dict(
              name="site1",
              ranges=[
                  "range1",
                  "range2"
              ]
          )
      ]
  
      requests = mock.Mock()
      requests.status_code = 200
      requests.json.return_value = {
          'args': {'some_mock_value': 'mocky'}
      }
  
      site_object = Site(sites[0]['name'], sites[0]['ranges'])
      assert site_object.name == "site1"
      assert isinstance(site_object.ranges_objects, list)
      assert site_object.ranges_objects[0].range_detail == dict(some_mock_value='mocky')
  </code></pre>