At work last week, I was asked to write tests for code that reaches out to Twilio's verify service. Here is what that code looks like (from the Twilio docs):
client = Client(account_sid, auth_token)
verification = client.verify \
.v2 \
.services('VAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX') \
.verifications \
.create(to='+15017122661', channel='sms')
I was able to use @mock.patch(module.Client)
* to mock the client, but I tried a few different ways, unsuccessfully, to patch the return value (or raise an exception) of create()
all the way down that chain. After a couple breaks and different incantations entered into Google, I finally stumbled upon what I needed in the docs for unittest.mock
, mocking chained calls.
I threw in a bunch of .return_value
s into my function call, and thought I had solved it, but that unfortunately didn't work. What I realized is that you only need those after the function calls (ones with parenthesis), not the properties (like verifications
, v2
, etc.). So the final product looks like:
@mock.patch(your_module.Client)
def test_name(mocked_client):
mocked_client.return_value.verify.v2.services.return_value.verifications.create.return_value = 'return value that I want'
...
# call the function
# assert some things
If you want to raise an exception:
from twilio.base.exceptions import TwilioRestException
...
@mock.patch(your_module.Client)
def test_name(mocked_client):
mocked_client.return_value.verify.v2.services.return_value.verifications.create.side_effect = TwilioRestException("", "")
...
# call the function
# assert some things
*Don't forget to mock the Client in your module, not the library itself in case other tests need the client.