0

I would like to write a unit test case for HTTPError exception part based on the error response content I get. But I have now idea how I can mock the response so that the unit test can reach doSomething1() instead of doSomething2().

foo.py

def get_result_from_API():  
   #Try to call API here...

def getSomething():
  try:
    result = get_result_from_API()
  except HTTPError as error:
    error_json = error.response.json()
    if error_json.get("error").get("code") == "00001":
      doSomething1()
    else:
      doSomething2()
      raise error

Unit Test

@patch('foo.doSomething2')
@patch('foo.doSomething1')
@patch('foo.get_result_from_API')    
def testGetSomething(get_result_from_API,doSomething1,doSomething2):
  mock_response = Mock()
  mock_response.return_value = {  
      "error":{                            
          "code": "00001",
          "message": "error message for foo reason"            
      }
  }
  get_result_from_API.side_effect = HTTPError(response=mock_response)

  with self.assertRaises(HTTPError):
    foo.getSomething()

  doSomething1.assert_called_once()

The current result is that doSomething1() is not called where as doSomething2() is called.

  • What's not working as expected? What error messaged do you see? Where is the code getting to? How have you tried to debug so far? – mackorone Jan 22 '22 at 08:03
  • The real code is somehow complicated. But it seems doSomething2() is called but doSomething1() is not. I would like the unit test to run through doSomething1(). – Zhuang Paulus Jan 24 '22 at 01:44
  • I suggest you add print statements to your program to debug. Print out `error_json`. Is it what you expect? Print out `error_json.get("error")`. Is that what you expect? Etc. – mackorone Jan 25 '22 at 05:13

1 Answers1

-1

Since the getSomething function calls:

error_json = error.response.json()

the solution is to mock the call to .json()

  mock_response.json.return_value = {  
      "error":{                            
          "code": "00001",
          "message": "error message for foo reason"            
      }
  }

As it was originally written, getSomething would have had to have called response() directly.

error_json = error.response()

Here is a more generic example:

>>> from unittest.mock import Mock                                                        
>>> mock_response = Mock() 
                                                               
>>> mock_response.return_value = {"hello": "world"}                                       
>>> mock_response()  # call response() directly
{'hello': 'world'}

>>> mock_response.json()  # no return_value is assigned to the json() call
<Mock name='mock.json()' id='4407756744'>

>>> mock_response.json.return_value = {"hello": "universe"} # assign a json() return_value                              
>>> mock_response.json()                                                              
{'hello': 'universe'}

If you want, you can even do this while instantiating Mock:

kcontr
  • 343
  • 2
  • 12