python - 如何在 Python/Django 中使用 AWS SNS (boto3/moto) 测试 SMS?

标签 python testing pytest boto3 moto

我正在开发一个 API,该 API 使用 AWS SNS 在某些端点中发送 SMS。在涉及这些端点的测试中,使用 mock_sns 装饰器。然而,对于发送的短信的数量或内容没有做出任何断言。我想这只是为了避免错误。然而,就我而言,我实际上需要检查是否发送了一条短信以及它是否包含特定文本。我怎样才能做到这一点?我的测试应该是什么样的?

我知道如何使用普通的 Python 模拟来做到这一点,但由于该项目已经有 moto 作为依赖项,我想我应该尝试一下,但我很惊讶我找不到这种简单用例的任何示例。或者也许我误解了这个库的目的?

@mock_sns
def test_my_endpoint():
    response = client.post("/my/endpoint/", ...)
    # assert one SMS was sent???
    # assert "FooBar" in SMS???

最佳答案

既然你想使用moto库,为什么不使用sqs来测试使用sns只发送了一个通知?

sns + sqs 连接,有时称为 fanout ,将实现指定的测试,因为通知将存储在 sqs 中,您可以在调用后立即查看它。检查下面的 test_fanout 方法。

另一方面,根据所提供的信息,我将使用 botocore stubs或 python 模拟来检查调用是否已按照您想要的方式进行。如果使用stubber,请检查下面的test_stubber_sms方法。

代码假设 moto >= 1.3.14、boto3 1.18、botocore 1.21.0 和 python 3.6.9:

from moto import mock_sns, mock_sqs
import unittest
import boto3
import json
from botocore.stub import Stubber


class TestBoto3(unittest.TestCase):

    @mock_sns
    @mock_sqs
    def test_fanout(self):
        region_name = "eu-west-1"
        topic_name = "test_fanout"
        sns, sqs = boto3.client("sns", region_name=region_name), boto3.client("sqs", region_name=region_name)

        topic_arn = sns.create_topic(Name=topic_name)["TopicArn"]
        sqs_url = sqs.create_queue(QueueName='test')["QueueUrl"]
        sqs_arn = sqs.get_queue_attributes(QueueUrl=sqs_url)["Attributes"]["QueueArn"]

        sns.subscribe(TopicArn=topic_arn, Protocol='sqs', Endpoint=sqs_arn)
        sns.subscribe(TopicArn=topic_arn, Protocol='sms', Endpoint="+12223334444")

        sns.publish(TopicArn=topic_arn, Message="test")
        sns.publish(PhoneNumber="+12223334444", Message="sms test")

        message = sqs.receive_message(QueueUrl=sqs_url, MaxNumberOfMessages=10)["Messages"]
        sqs.delete_message(QueueUrl=sqs_url, ReceiptHandle=message[0]["ReceiptHandle"])

        self.assertEqual(len(message), 2)
        self.assertEqual(json.loads(message[0]["Body"])["Message"], 'test')
        self.assertEqual(json.loads(message[1]["Body"])["Message"], 'sms test')

    def test_stubber_sms(self):
        sns = boto3.client("sns")
        stubber = Stubber(sns)

        stubber.add_response(method='publish', service_response={"MessageId": '1'}, expected_params={'PhoneNumber':"+12223334444", 'Message':"my message"})
        with stubber:
            response = sns.publish(PhoneNumber="+12223334444", Message="my message")
            # Or use your method and pass boto3 sns client as argument
            self.assertEqual(response, {"MessageId": '1'})
            stubber.assert_no_pending_responses()

if __name__ == '__main__':
    unittest.main()

关于python - 如何在 Python/Django 中使用 AWS SNS (boto3/moto) 测试 SMS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61080494/

相关文章:

python - 如何在没有人为干预的情况下回答从 python 脚本调用的 bash 脚本提出的问题

单值返回与嵌套的 Python 列表理解

testing - 如何在加载 url 时处理证书

python - 使用 pytest-xdist 跨主节点和工作节点访问共享资源

python - 在 python 2.7 windows 中安装请求模块

Python/SQLite - 尽管超时时间长,但数据库仍被锁定

testing - Sinon 监视所有方法调用

python - 排除目录,python nosetest中的模块

python - 如何将函数作为 pytest 参数化装置传递?

python - 如何使用mockito模拟os.path.join