Reputation: 515
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
Upvotes: 10
Views: 22455
Reputation: 308
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.
Upvotes: 13