模拟twilio休息客户端进行测试

sta*_*tic 6 django unit-testing twilio

我使用以下代码发送短信.

 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)
Run Code Online (Sandbox Code Playgroud)

嘲笑twilio api的正确方法是什么?

我在用 twilio 6.5.2

Bor*_*rov 15

您可以在此处使用两种方法:

  1. 使用假的twilio客户端并用于单元测试代码
  2. 使用真实客户端与测试帐户

对于单元测试,方法1通常是一个更好的想法,因此,例如,您可以离线运行测试并更快地执行测试.此外,您需要测试您的代码,但使用方法2,您也将测试twilio本身.

这带来了另一个问题:我们如何确保您的假客户端与真实客户端的工作距离足够近以使您的测试有用?在最好的情况下,twilio会释放并维护这样的测试客户端,但看起来并不像他们拥有它.

您可以做的是结合这些方法:拥有虚假客户端(方法1)并进行一些测试以验证您的虚假客户端与真实客户端的行为相同.

但是你可以从方法1开始 - 你需要构建你的测试客户端(通常是超级简单的东西),并确保它与真实的客户端工作距离足够近(可能切换到真正的客户端并确保你的测试仍然工作).

这里的危险是,如果在twilio端有一些重大的API更改,你的测试仍然会通过,虽然真正的应用程序将被打破.另一方面,即使测试失败,真正的应用程序仍然会被破坏,因此在这种情况下你无法真正保护你的应用程序.

以下是我们如何为您的代码创建测试客户端:

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
        })
Run Code Online (Sandbox Code Playgroud)

在测试中,您可以执行以下操作:

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
})
Run Code Online (Sandbox Code Playgroud)

这是一种简化的方法,另外您可以使用模拟库来制作测试客户端.

或者您可以修补真正的twilio客户端,仅阻止实际的HTTP请求并记录参数/模拟响应.您将需要查看twilio客户端源代码以找到要模拟的方法(或方法),这里是类似的方法我用来模拟facebook图形响应通过模拟库的Session.request方法requests:

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)
Run Code Online (Sandbox Code Playgroud)

现在,当应用程序尝试从facebook API获取数据时,它将获取静态数据,而数据将被包装到ResponseMock对象中,这是我们从实际请求中获得的最小代表.

另请参阅本文:使用Python的Flask和Nose对您的Twilio应用程序进行单元测试.据我所知,他们使用真正的客户端进行单元测试,但他们也提到了集成的另一面 - 如何测试从twilio端调用的代码.在这种情况下,您还需要模拟Twilio服务器,本文中有一个此类仿真的示例.