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_client
to 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
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.
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.
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 .
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With