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

时间:2017-10-20 13:01:59

标签: 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)

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

我正在使用twilio 6.5.2

2 个答案:

答案 0 :(得分:10)

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

  1. 使用假的twilio客户端并用于对代码进行单元测试
  2. 使用真实客户端和测试帐户
  3. 对于单元测试,方法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客户端源代码以找到要模拟的方法(或方法),这里是我习惯的类似方法 通过模拟Session.request库的requests方法来模拟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服务器,文章中有一个这样的仿真示例。

答案 1 :(得分:1)

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

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

正如@txfun在评论中所建议的那样,请参阅twilio Free account链接