Is it possible to mock Eventbridge pattern matching, confirmed by the receipt of a pattern- matched message into an SQS queue ?
Asking as I have a boto3/moto script (below) which attempts to do this and which I believe should work, but .. it's not :/
I think this probably falls under the title "complex mocked AWS workflows never behave exactly the way they do in the cloud", but it's possible I've made a mistake somewhere.
Anyone know if testing of Eventbridge pattern matching should be possible in this way (or not) or if I am doing something wrong ?
TIA
import boto3, json, unittest
from datetime import datetime
from moto import mock_events, mock_sqs
QueueName, RuleName = "hello-queue", "hello-rule"
RuleTargetId, RuleEnabled = "hello-rule-target", "ENABLED"
EventSource, EventDetailType, EventResource = "hello-event-source", "hello-event-detail-type", "event-resource"
@mock_events
@mock_sqs
class HelloTest(unittest.TestCase):
def setUp(self):
self.sqs, self.events = (boto3.client("sqs"),
boto3.client("events"))
statement=[{"Effect": "Allow",
"Principal": {"Service": "events.amazonaws.com"},
"Action": "sqs:SendMessage",
"Resource": "*"}]
policy=json.dumps({"Version": "2012-10-17",
"Statement": [statement]})
queue=self.sqs.create_queue(QueueName=QueueName,
Attributes={"Policy": policy})
self.queueurl=queue["QueueUrl"]
queueattrs=self.sqs.get_queue_attributes(QueueUrl=self.queueurl)
self.queuearn=queueattrs["Attributes"]["QueueArn"]
eventpattern={"source": [EventSource],
"detail": {"hello": ["world"]}}
self.rule=self.events.put_rule(Name=RuleName,
State=RuleEnabled,
EventPattern=json.dumps(eventpattern))
self.events.put_targets(Rule=RuleName,
Targets=[{"Id": RuleTargetId,
"Arn": self.queuearn}])
# test that simple SQS send/receive works in moto
def test_sqs_message(self):
reqbody=json.dumps({"hello": "world"})
self.sqs.send_message(QueueUrl=self.queueurl,
MessageBody=reqbody)
sqsresp=self.sqs.receive_message(QueueUrl=self.queueurl)
self.assertTrue("Messages" in sqsresp)
messages=sqsresp["Messages"]
self.assertTrue(len(messages), 1)
message=messages.pop()
body=json.loads(message["Body"])
self.assertTrue("hello" in body)
# test that more complex Eventbridge+SQS workflow works
def test_eventbridge_message(self):
detail=json.dumps({"hello": "world"})
entry={"Time": datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"),
"Source": EventSource,
"Resources": [EventResource],
"DetailType": EventDetailType,
"Detail": detail}
self.events.put_events(Entries=[entry])
sqsresp=self.sqs.receive_message(QueueUrl=self.queueurl)
# self.assertTrue("Messages" in sqsresp) # <--- FAILS HERE
def tearDown(self):
self.sqs.delete_queue(QueueUrl=self.queueurl)
self.events.remove_targets(Rule=RuleName,
Ids=[RuleTargetId])
self.events.delete_rule(Name=RuleName)
if __name__=="__main__":
unittest.main()