I am using the following code to send SMS.
from twilio.rest import Client
from django.conf import settings
def send_sms(phone, content=generate_sms_code()):
client = Client(settings.ACCOUNT_SID, settings.AUTH_TOKEN)
return client.messages.create(
to=phone,
from_=settings.FROM_DEFAULT_NUMBER,
body=content)
what is the proper way of mocking twilio api?
I am using twilio
6.5.2
There are two approaches you can use here:
For unit tests the approach 1 is usually a better idea, so, for example, you can run your tests offline and the tests are executed faster. Also you need to test your code, but with approach 2 you will also be testing twilio itself.
That brings another problem: how do we make sure that your fake client works close enough to the real client to make your tests useful? In the best case, twilio would release and maintain such test client, but it doesn't look like they have it.
What you can do is to combine the approaches: have the fake client (approach 1) and have some tests to verify that your fake client behaves same as real one.
But you can start with just the approach 1 - you need to build your test client (usually something super-simple) and make sure that it works close enough to the real one (maybe switch to the real client and make sure that your tests still work).
The danger here is that if there were some breaking API changes on twilio side, your tests would still be passing, although the real app will be broken. On the other hand, even if the tests were failing, the real app would still be broken, so you can't really protect your app in this scenario.
Here is how we could make a test client for your code:
class TwilioTestClient:
def __init__(self, sid, token):
self.sid = sid
self.token = token
self.messages = TwillioTestClientMessages()
class TwillioTestClientMessages:
self.created = []
def create(self, to, from_, body):
self.created.append({
'to': to,
'from_': from_,
'body': body
})
And in your test you can then do something like this:
import twilio
# Replace real client with our test client
twilio.Client = TwilioTestClient
// invoke your code
send_sms(phone, content)
assert TwillioTestClientMessages.created == [{
'to': phone,
'from_': settings.DEFAULT_NUMBER,
'body': content
})
This is a simplified approach, additionally you can use mock library to make the test client.
Or you can patch the real twilio client to only block actual HTTP requests and record the parameters / emulate the response.
You will need to look into twilio client source code to find the method (or methods) to mock, here is similar approach I've used to
mock facebook graph response by mocking the Session.request
method of the requests
library:
mock_facebook_data = {
'id': 'test_id',
'first_name': 'First Name',
'last_name': 'Last Name'
}
def get_facebook_data(self, method, url, **kwargs):
# Make sure we are mocking the expected request.
assert method == 'get'
assert url == (
'https://graph.facebook.com/me?fields=first_name,id,'
'last_name&access_token={}'.format(facebook_access_token)
)
class ResponseMock:
def __init__(self, data):
self.data = data
self.status_code = 200
def json(self):
return self.data
return ResponseMock(mock_facebook_data)
monkeypatch.setattr('requests.sessions.Session.request', get_facebook_data)
Now, when the app tries to fetch the data from facebook API, it will get the static data instead and that data will be wrapped into the ResponseMock
object, minimal representation of what we would get from the real request.
Also check this article: Unit Testing Your Twilio App Using Python’s Flask and Nose. As I understand, they are using real client for unit tests, but they also mention the other side of the integration - how to test your code that is being invoked from the twilio side. In this case you also need to emulate the Twilio server and there is an example of such emulation in the article.
If you want to test SMS functionality of twilio using apis, you can create a free twilio account to test it.
But I would recommend using environment specific values for the account SID, auth token etc. You would want to seperate your production environment from testing/development environment, so the same piece of code runs over both the environment with different twilio accounts.
As suggested by @txfun in the comments, refer twilio Free account link
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