【问题标题】:mock twilio rest client for testing用于测试的模拟 twilio 休息客户端
【发布时间】:2017-10-20 13:01:59
【问题描述】:

我正在使用以下代码发送短信。

 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)

模拟 twilio api 的正确方法是什么?

我正在使用twilio6.5.2

【问题讨论】:

  • 您可以从 twilio 注册一个免费的 api-key,您可以使用 twillio 创建一个帐户并玩转。 support.twilio.com/hc/en-us/articles/…。如果您的意图是测试各种 twilio 场景的代码,您应该使用 Mocking 库进行单元/端到端测试

标签: django unit-testing twilio


【解决方案1】:

您可以在这里使用两种方法:

  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
        })

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

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
})

这是一种简化的方法,另外您可以使用mock library 来制作测试客户端。

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

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)

现在,当应用尝试从 facebook API 获取数据时,它会改为获取静态数据,并且该数据将被包装到 ResponseMock 对象中,这是我们从真实请求中获得的最小表示。

还可以查看这篇文章:Unit Testing Your Twilio App Using Python’s Flask and Nose。据我了解,他们使用真正的客户端进行单元测试,但他们也提到了集成的另一面——如何测试从 twilio 端调用的代码。 在这种情况下,您还需要模拟 Twilio 服务器,本文中提供了此类模拟的示例。

【讨论】:

    【解决方案2】:

    如果您想使用 api 测试 twilio 的短信功能,您可以创建一个免费的 twilio 帐户进行测试。

    但我建议对帐户 SID、身份验证令牌等使用特定于环境的值。您可能希望将生产环境与测试/开发环境分开,因此同一段代码在具有不同 twilio 帐户的环境中运行。

    根据 cmets 中@txfun 的建议,参考twilio Free account 链接

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-03
      相关资源
      最近更新 更多