title: Pytest fixtures in requests post function
body: <p>I'm trying to understand the example provided <a href="https://docs.pytest.org/en/7.1.x/how-to/monkeypatch.html#monkeypatching-returned-objects-building-mock-classes" rel="nofollow noreferrer">here</a> and emulate it to work for the <code>post</code> method instead of <code>get</code> method.</p>
  <p>All works well when I'm testing for <code>response.status_code == 200</code>. How do I test for more than one response status codes without repeating the code (like in <a href="https://www.patricksoftwareblog.com/monkeypatching-with-pytest/" rel="nofollow noreferrer">here</a>?
  I understand that one needs to use fixtures, how do I leverage them?</p>
  <p>This is where I'm up to now.</p>
  <pre><code>app.py
  
  from typing import Dict, Union
  from urllib.error import HTTPError
  
  import requests
  import structlog
  
  logger = structlog.get_logger()
  
  
  def get_access_token(
      url: str, client_id: str, client_secret: str, grant_type: str
  ) -&gt; Union[Dict[str, Union[str, int]], None]:
      try:
          r = requests.post(
              url,
              data={&quot;grant_type&quot;: grant_type},
              auth=(client_id, client_secret),
              verify=True,
          )
          logger.info(&quot;Fetching token status code&quot;, status_code=r.status_code)
      except HTTPError as http_err:
          logger.error(&quot;HTTP error occurred&quot;, http_error=str(http_err))
      except Exception as err:
          logger.error(&quot;Other error occurred&quot;, exception=str(err))
      else:
          # The token expires in 10800 seconds
          return r.json()
  </code></pre>
  <pre><code>test_app.py
  
  # contents of test_app.py, a simple test for our API retrieval
  from typing import Dict, Union
  
  import pytest
  import requests
  
  from app import get_access_token
  
  
  # custom class to be the mock return value of requests.post()
  class MockResponse:
      status_code = 200
      raise_for_status = None
  
      @staticmethod
      def json() -&gt; Dict[str, Union[str, int]]:
          return {
              'access_token': 'fake-access-token',
              'token_type': 'fake-token-type',
              'expires_in': 10800,
          }
  
  @pytest.fixture
  def mock_response(monkeypatch):
      &quot;&quot;&quot;Requests.post() mocked to return json.&quot;&quot;&quot;
  
      def mock_post(*args, **kwargs):
          return MockResponse()
  
      monkeypatch.setattr(requests, &quot;post&quot;, mock_post)
  
  
  # notice our test uses the custom fixture instead of monkeypatch directly
  def test_get_access_token_success(mock_response) -&gt; None:
      result = get_access_token(
          url=&quot;https://fakeurl&quot;,
          client_id=&quot;fake-client-id&quot;,
          client_secret=&quot;fake-client-secret&quot;,
          grant_type=&quot;fake-grant-type&quot;,
      )
      assert result['access_token'] == &quot;fake-access-token&quot;
      assert result['token_type'] == &quot;fake-token-type&quot;
  </code></pre>
  <p>rewrote app.py after @gold_cy's suggestion</p>
  <pre><code>from typing import Dict, Union
  
  import requests
  import structlog
  
  logger = structlog.get_logger()
  
  
  def get_access_token(
      url: str,
      client_id: str,
      client_secret: str,
      grant_type: str = 'client_credentials',
  ) -&gt; Dict[str, Union[str, int]]:
      try:
          r = requests.post(
              url,
              data={&quot;grant_type&quot;: grant_type},
              auth=(client_id, client_secret),
              verify=True,
          )
          logger.info(&quot;Fetching token status code&quot;, status_code=r.status_code)
          r.raise_for_status()
          if r.status_code == 200:
              # FIXME: The token expires in 10800 seconds
              return r.json()
      except requests.exceptions.HTTPError as err:
          logger.error(&quot;HTTP error&quot;, request=err.response.text)
          raise requests.HTTPError(err)
  </code></pre>