11import unittest
2- import os
32from unittest .mock import patch , MagicMock
43from botocore .exceptions import ClientError
5- from sample_data .test_resource_data import get_test_data_resource
4+ import os
5+ from tests .sample_data .test_resource_data import get_test_data_resource
66
77# Set environment variables before importing the module
88os .environ ["AWS_SQS_QUEUE_URL" ] = "https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue"
99os .environ ["DELTA_TABLE_NAME" ] = "my_delta_table"
1010os .environ ["SOURCE" ] = "my_source"
11- os .environ ["SPLUNK_FIREHOSE_NAME" ] = "my_firehose"
1211
1312from src .delta import send_message , handler # Import after setting environment variables
1413import json
1514
1615
16+
1717class DeltaTestCase (unittest .TestCase ):
1818
1919 def setUp (self ):
2020 # Common setup if needed
2121 self .context = {}
22+ self .logger_exception_patcher = patch ("logging.Logger.exception" )
23+ self .mock_logger_exception = self .logger_exception_patcher .start ()
24+
25+ self .firehose_logger_patcher = patch ("src.delta.firehose_logger" )
26+ self .mock_firehose_logger = self .firehose_logger_patcher .start ()
27+ self .mock_firehose_logger .send_log = MagicMock ()
28+
29+
30+ def tearDown (self ):
31+ self .logger_exception_patcher .stop ()
32+ self .mock_firehose_logger .stop ()
2233
2334 @staticmethod
2435 def setup_mock_sqs (mock_boto_client , return_value = {"ResponseMetadata" : {"HTTPStatusCode" : 200 }}):
2536 mock_sqs = mock_boto_client .return_value
2637 mock_sqs .send_message .return_value = return_value
2738 return mock_sqs
2839
29- @staticmethod
30- def setup_mock_firehose (mock_boto_client , return_value = {"ResponseMetadata" : {"HTTPStatusCode" : 200 }}):
31- mock_firehose = mock_boto_client .return_value
32- mock_firehose .put_record .return_value = return_value
33- return mock_firehose
34-
35- @staticmethod
36- def setup_mock_firehose (mock_boto_client , return_value = {"ResponseMetadata" : {"HTTPStatusCode" : 200 }}):
37- mock_firehose = mock_boto_client .return_value
38- mock_firehose .put_record .return_value = return_value
39- return mock_firehose
40-
41-
4240 @staticmethod
4341 def setup_mock_dynamodb (mock_boto_resource , status_code = 200 ):
44- """
45- Sets up a mock for boto3.resource("dynamodb") and its Table method.
46- """
47- # Mock the DynamoDB resource
4842 mock_dynamodb = mock_boto_resource .return_value
49-
50- # Mock the Table method
51- mock_table = MagicMock ()
52- mock_dynamodb .Table .return_value = mock_table
53-
54- # Mock the put_item method of the table
43+ mock_table = mock_dynamodb .Table .return_value
5544 mock_table .put_item .return_value = {"ResponseMetadata" : {"HTTPStatusCode" : status_code }}
56-
5745 return mock_table
5846
5947 def setUp_mock_resources (self , mock_boto_resource , mock_boto_client ):
@@ -123,8 +111,8 @@ def test_send_message_success(self, mock_boto_client):
123111 )
124112
125113 @patch ("boto3.client" )
126- @patch ("logging.Logger.info " )
127- def test_send_message_client_error (self , mock_logger_info , mock_boto_client ):
114+ @patch ("logging.Logger.error " )
115+ def test_send_message_client_error (self , mock_logger_error , mock_boto_client ):
128116 # Arrange
129117 mock_sqs = MagicMock ()
130118 mock_boto_client .return_value = mock_sqs
@@ -138,33 +126,27 @@ def test_send_message_client_error(self, mock_logger_info, mock_boto_client):
138126 send_message (record )
139127
140128 # Assert
141- mock_logger_info .assert_called_once_with (
129+ mock_logger_error .assert_called_once_with (
142130 f"Error sending record to DLQ: An error occurred (500) when calling the SendMessage operation: Internal Server Error"
143131 )
144132
145- @patch ("delta.FirehoseLogger.send_log" )
146133 @patch ("boto3.resource" )
147- def test_handler_success_insert (self , mock_boto_resource , mock_send_log ):
134+ def test_handler_success_insert (self , mock_boto_resource ):
148135 # Arrange
149- mock_send_log .return_value = None
150136 self .setup_mock_dynamodb (mock_boto_resource )
151137 suppilers = ["DPS" , "EMIS" ]
152138 for supplier in suppilers :
153139 event = self .get_event (supplier = supplier )
154- for record in event ["Records" ]:
155- record ["dynamodb" ]["NewImage" ]["Resource" ]["S" ] = json .dumps (get_test_data_resource ())
156140
157141 # Act
158142 result = handler (event , self .context )
159143
160144 # Assert
161145 self .assertEqual (result ["statusCode" ], 200 )
162146
163- @patch ("delta.FirehoseLogger.send_log" )
164147 @patch ("boto3.resource" )
165- def test_handler_failure (self , mock_boto_resource , mock_send_log ):
148+ def test_handler_failure (self , mock_boto_resource ):
166149 # Arrange
167- mock_send_log .return_value = None
168150 self .setup_mock_dynamodb (mock_boto_resource , status_code = 500 )
169151 event = self .get_event ()
170152
@@ -174,11 +156,9 @@ def test_handler_failure(self, mock_boto_resource, mock_send_log):
174156 # Assert
175157 self .assertEqual (result ["statusCode" ], 500 )
176158
177- @patch ("delta.FirehoseLogger.send_log" )
178159 @patch ("boto3.resource" )
179- def test_handler_success_update (self , mock_boto_resource , mock_send_log ):
160+ def test_handler_success_update (self , mock_boto_resource ):
180161 # Arrange
181- mock_send_log .return_value = None
182162 self .setup_mock_dynamodb (mock_boto_resource )
183163 event = self .get_event (event_name = "UPDATE" , operation = "UPDATE" )
184164
@@ -188,11 +168,9 @@ def test_handler_success_update(self, mock_boto_resource, mock_send_log):
188168 # Assert
189169 self .assertEqual (result ["statusCode" ], 200 )
190170
191- @patch ("delta.FirehoseLogger.send_log" )
192171 @patch ("boto3.resource" )
193- def test_handler_success_remove (self , mock_boto_resource , mock_send_log ):
172+ def test_handler_success_remove (self , mock_boto_resource ):
194173 # Arrange
195- mock_send_log .return_value = None
196174 self .setup_mock_dynamodb (mock_boto_resource )
197175 event = self .get_event (event_name = "REMOVE" , operation = "DELETE" )
198176
@@ -202,12 +180,10 @@ def test_handler_success_remove(self, mock_boto_resource, mock_send_log):
202180 # Assert
203181 self .assertEqual (result ["statusCode" ], 200 )
204182
205- @patch ("delta.FirehoseLogger.send_log" ) # Patch the method directly
206183 @patch ("boto3.resource" )
207184 @patch ("boto3.client" )
208- def test_handler_exception_intrusion_check (self , mock_boto_resource , mock_boto_client , mock_send_log ):
185+ def test_handler_exception_intrusion_check (self , mock_boto_resource , mock_boto_client ):
209186 # Arrange
210- mock_send_log .return_value = None
211187 self .setup_mock_dynamodb (mock_boto_resource , status_code = 500 )
212188 mock_boto_client .return_value = MagicMock ()
213189 event = self .get_event ()
@@ -217,73 +193,53 @@ def test_handler_exception_intrusion_check(self, mock_boto_resource, mock_boto_c
217193 result = handler (event , self .context )
218194 self .assertEqual (result ["statusCode" ], 500 )
219195
220- @patch ("delta.FirehoseLogger.send_log" ) # Patch the method directly
221196 @patch ("boto3.resource" )
222197 @patch ("boto3.client" )
223- def test_handler_exception_intrusion (self , mock_boto_resource , mock_boto_client , mock_send_log ):
198+ def test_handler_exception_intrusion (self , mock_boto_client , mock_boto_resource ):
224199 # Arrange
225200 self .setUp_mock_resources (mock_boto_resource , mock_boto_client )
226- mock_send_log . return_value = None
201+
227202 event = self .get_event ()
228203 context = {}
229204
230205 # Act & Assert
231206 with self .assertRaises (Exception ):
232207 handler (event , context )
233208
234- @patch ("delta.FirehoseLogger.send_log" )
209+ self .mock_logger_exception .assert_called_once_with ("Delta Lambda failure: Test Exception" )
210+
235211 @patch ("boto3.resource" )
236212 @patch ("delta.handler" )
237- def test_handler_exception_intrusion_check_false (self , mock_boto_resource , mock_boto_client , mock_send_log ):
213+ def test_handler_exception_intrusion_check_false (self , mocked_intrusion , mock_boto_client ):
238214 # Arrange
239- mock_send_log .return_value = None
240- self .setUp_mock_resources (mock_boto_resource , mock_boto_client )
215+ self .setUp_mock_resources (mocked_intrusion , mock_boto_client )
241216 event = self .get_event ()
242217 context = {}
243218
244219 # Act & Assert
245220 with self .assertRaises (Exception ):
246221 handler (event , context )
247222
248- @patch ("delta.FirehoseLogger.send_log" ) # Patch the method directly
249- @patch ("boto3.client" )
250- @patch ("delta.logger.info" )
251- def test_dps_record_skipped (self , mock_logger_info , mock_boto_client , mock_send_log ):
252- """
253- Test that DPSFULL records are skipped and Firehose put_record is mocked.
254- """
255- # Arrange
256- mock_firehose_client = self .setup_mock_firehose (mock_boto_client )
257-
258- mock_send_log .return_value = None
223+ @patch ("delta.logger.info" ) # Mock logging
224+ def test_dps_record_skipped (self , mock_logger_info ):
259225
260- # Create a test event with supplier "DPSFULL"
261226 event = self .get_event (supplier = "DPSFULL" )
262227 context = {}
263228
264- # Act
265229 response = handler (event , context )
230+ print (f"final response1: { response } " )
266231
267- # Assert
268- # check send_log was called
269- mock_send_log .assert_called_once ()
270232 self .assertEqual (response ["statusCode" ], 200 )
271233 self .assertEqual (response ["body" ], "Record from DPS skipped for 12345" )
272234
273- # Check logging was called
235+ # Check logging and Firehose were called
274236 mock_logger_info .assert_called_with ("Record from DPS skipped for 12345" )
275237
276- # Ensure Firehose put_record was not called since DPSFULL records are skipped
277- mock_firehose_client .put_record .assert_not_called ()
278-
279- # # TODO - amend test once error handling implemented
280- @patch ("delta.FirehoseLogger.send_log" ) # Patch the method directly
238+ # TODO - amend test once error handling implemented
281239 @patch ("delta.logger.info" )
282240 @patch ("Converter.Converter" )
283241 @patch ("delta.boto3.resource" )
284- def test_partial_success_with_errors (self , mock_dynamodb , mock_converter , mock_logger_info , mock_send_log ):
285-
286- mock_send_log .return_value = None
242+ def test_partial_success_with_errors (self , mock_dynamodb , mock_converter , mock_logger_info ):
287243 mock_converter_instance = MagicMock ()
288244 mock_converter_instance .runConversion .return_value = [{}]
289245 mock_converter_instance .getErrorRecords .return_value = [{"error" : "Invalid field" }]
0 commit comments