我正在研究一个API,该API使用AWS SNS在某些端点中发送SMS。在接触这些端点的测试中,使用mock_sns
装饰器。但是,没有断言有关发送的SMS消息的数量或内容。我想这只是为了避免错误。但是,就我而言,我实际上需要检查是否已发送一条SMS消息,并且其中包含特定文本。我怎样才能做到这一点?我的测试应该如何?
我知道如何使用普通的Python模拟进行操作,但是由于该项目已经具有moto
作为依赖项,所以我想尝试一下,但是很惊讶,我找不到任何示例这样简单的用例。还是我误解了这个库的目的?
@mock_sns
def test_my_endpoint():
response = client.post("/my/endpoint/", ...)
# assert one SMS was sent???
# assert "FooBar" in SMS???
答案 0 :(得分:0)
不幸的是,似乎没有直接的方法可以执行此操作,因为boto3
库中没有这样的API调用。
您可以做的是创建一个订户(模拟),注册到sns并在该订户上声明。可以在moto
iteslf的内部测试中找到此类测试的示例:
@mock_sns
def test_publish_sms():
client = boto3.client("sns", region_name="us-east-1")
client.create_topic(Name="some-topic")
resp = client.create_topic(Name="some-topic")
arn = resp["TopicArn"]
client.subscribe(TopicArn=arn, Protocol="sms", Endpoint="+15551234567")
result = client.publish(PhoneNumber="+15551234567", Message="my message")
result.should.contain("MessageId")
来自:https://github.com/spulec/moto/blob/master/tests/test_sns/test_publishing_boto3.py
答案 1 :(得分:0)
既然要使用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()