简体   繁体   中英

How to mock HTTPError response in Python unit test

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.

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:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM