2

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()
scrowler
  • 24,273
  • 9
  • 60
  • 92
Justin
  • 4,649
  • 6
  • 33
  • 71
  • 1
    Which version of Moto are you on? This integration should work as of moto >= 2.0.5.dev8 - see https://github.com/spulec/moto/pull/3830 – Bert Blommers Jul 07 '21 at 16:55
  • @BertBlommers works! Thank you so much. I was on an old version 1.3.14 - I think in the past I had a lot of problems with 1.3.15 and never upgraded past that. Great to see how much moto is evolving and improving :) – Justin Jul 08 '21 at 11:12

0 Answers0