Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Requests - Mock status code and response

So I'm writing some unit tests for a Python project and I want to mock a response to an external API.

My code looks like this:

r = my_api_client.get(myurl)

try:
    if r.status_code == 200:
        my_response = r.json()
    elif r.status_code != 200:
        print "bad status code"
except Exception as e:
    raise

for x in my_response:
    ...

My question is how do I mock my_api_clientto return a proper status code and json object?

I've been trying things like my_api_client = mock.Mock(return_value={'status_code':200, 'json_obj': {'blah':'blah'}})

Thanks for any help

like image 822
Strobe_ Avatar asked Mar 06 '17 16:03

Strobe_


People also ask

How do you mock a status code in Python?

status_code = 200 is doing. When the status_code property is called on the mock, it will return 200 just like the actual object. The get_users() function will return the response, which is the mock, and the test will pass because the mock response status code is 200.

What is Side_effect in mock Python?

side_effect: A function to be called whenever the Mock is called. See the side_effect attribute. Useful for raising exceptions or dynamically changing return values. The function is called with the same arguments as the mock, and unless it returns DEFAULT , the return value of this function is used as the return value.

How do you make a mock in Python?

If you want to mock an object for the duration of your entire test function, you can use patch() as a function decorator. These functions are now in their own file, separate from their tests. Next, you'll re-create your tests in a file called tests.py .


1 Answers

You can compose a complex mock for the response, like this:

ok_response_mock = mock.MagicMock()
type(ok_response_mock).status_code = mock.PropertyMock(return_value=200)
ok_response_mock.json.return_value = "{'blah':'blah'}"

This creates a MagicMock (that doesn't complain when asked for non-speficied methods), adds the status_code property to it, which returns 200. And configures the JSON string response to the .json() method.

So, if my_api_client is a parameter in your test method:

my_api_client_mock = mock.MagicMock()
my_api_client_mock.get.return_value = ok_response_mock
YourModule.YourMethod(my_api_client_mock)

This creates the mock parameter, connects it to the previously created mock response and calls the test method. If, instead, my_api_client is an imported module:

@mock.patch('MyModuleUnderTest.my_api_client')
def test_MyMethodUnderTest__response_ok__stuff_happens(self, api_client_mock):
   # code to create ok_response_mock
   api_client_mock.get.return_value = ok_response_mock

This will patch the imported module with a mock, automatically created for you and placed as an argument to your test method. Just tell that mock to return the mocked response.

like image 84
Guido Avatar answered Sep 24 '22 03:09

Guido