Skip to content

Commit 1f53957

Browse files
committed
unit tests
1 parent 79c49f0 commit 1f53957

File tree

5 files changed

+111
-9
lines changed

5 files changed

+111
-9
lines changed

lambdas/ack_backend/src/ack_processor.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import json
44

5-
# from audit_table import increment_record_counter
5+
from audit_table import increment_records_failed_count
66
from common.batch.eof_utils import is_eof_message
77
from convert_message_to_ack_row import convert_message_to_ack_row
88
from logging_decorators import ack_lambda_handler_logging_decorator
@@ -51,9 +51,7 @@ def lambda_handler(event, _):
5151

5252
ack_data_rows.append(convert_message_to_ack_row(message, created_at_formatted_string))
5353
if message.get("diagnostics"):
54-
# TODO: unit tests will fail; we need to mock the audit table to get this to work.
55-
print("TODO: increment the record counter")
56-
# increment_record_counter(message_id)
54+
increment_records_failed_count(message_id)
5755

5856
update_ack_file(file_key, created_at_formatted_string, ack_data_rows)
5957

lambdas/ack_backend/src/update_ack_file.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44

55
from botocore.exceptions import ClientError
66

7-
from audit_table import change_audit_table_status_to_processed, get_record_count_by_message_id
7+
from audit_table import (
8+
change_audit_table_status_to_processed,
9+
get_record_count_by_message_id,
10+
set_records_succeeded_count,
11+
)
812
from common.aws_s3_utils import move_file
913
from common.clients import get_s3_client, logger
1014
from constants import (
@@ -73,9 +77,7 @@ def complete_batch_file_process(
7377

7478
total_ack_rows_processed = get_record_count_by_message_id(message_id)
7579
change_audit_table_status_to_processed(file_key, message_id)
76-
# TODO: we need to mock this here to pass unit tests
77-
print("TODO: Call set_record_success_count")
78-
# set_record_success_count(message_id)
80+
set_records_succeeded_count(message_id)
7981

8082
return {
8183
"message_id": message_id,

lambdas/ack_backend/tests/test_ack_processor.py

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,19 @@ def assert_audit_entry_status_equals(self, message_id: str, status: str) -> None
111111
actual_status = audit_entry.get("status", {}).get("S")
112112
self.assertEqual(actual_status, status)
113113

114+
def assert_audit_entry_counts_equal(self, message_id: str, expected_counts: dict) -> None:
115+
"""Checks the audit entry counts are as expected"""
116+
audit_entry = self.dynamodb_client.get_item(
117+
TableName=AUDIT_TABLE_NAME, Key={"message_id": {"S": message_id}}
118+
).get("Item")
119+
120+
actual_counts = {}
121+
actual_counts["record_count"] = audit_entry.get("record_count", {}).get("N")
122+
actual_counts["records_succeeded"] = audit_entry.get("records_succeeded", {}).get("N")
123+
actual_counts["records_failed"] = audit_entry.get("records_failed", {}).get("N")
124+
125+
self.assertEqual(actual_counts, expected_counts)
126+
114127
def test_lambda_handler_main_multiple_records(self):
115128
"""Test lambda handler with multiple records."""
116129
# Set up an audit entry which does not yet have record_count recorded
@@ -164,6 +177,11 @@ def test_lambda_handler_main_multiple_records(self):
164177
{"body": json.dumps(array_of_mixed_success_and_failure_messages)},
165178
]
166179
}
180+
expected_entry_counts = {
181+
"record_count": None,
182+
"records_succeeded": None,
183+
"records_failed": "6",
184+
}
167185

168186
response = lambda_handler(event=event, context={})
169187

@@ -177,6 +195,7 @@ def test_lambda_handler_main_multiple_records(self):
177195
],
178196
existing_file_content=ValidValues.ack_headers,
179197
)
198+
self.assert_audit_entry_counts_equal("row", expected_entry_counts)
180199

181200
def test_lambda_handler_main(self):
182201
"""Test lambda handler with consitent ack_file_name and message_template."""
@@ -217,12 +236,20 @@ def test_lambda_handler_main(self):
217236
"messages": [{"row_id": "row^1", "diagnostics": "SHOULD BE A DICTIONARY, NOT A STRING"}],
218237
},
219238
]
239+
expected_records_failed = [None, "3", "8", "8", "9"]
240+
expected_entry_counts = {
241+
"record_count": None,
242+
"records_succeeded": None,
243+
"records_failed": None,
244+
}
220245

221-
for test_case in test_cases:
246+
for test_case, expected_failures in zip(test_cases, expected_records_failed):
247+
expected_entry_counts["records_failed"] = expected_failures
222248
# Test scenario where there is no existing ack file
223249
with self.subTest(msg=f"No existing ack file: {test_case['description']}"):
224250
response = lambda_handler(event=self.generate_event(test_case["messages"]), context={})
225251
self.assertEqual(response, EXPECTED_ACK_LAMBDA_RESPONSE_FOR_SUCCESS)
252+
self.assert_audit_entry_counts_equal("row", expected_entry_counts)
226253
validate_ack_file_content(self.s3_client, test_case["messages"])
227254

228255
self.s3_client.delete_object(
@@ -252,6 +279,11 @@ def test_lambda_handler_updates_ack_file_but_does_not_mark_complete_when_records
252279
for i in range(1, 4)
253280
]
254281
test_event = {"Records": [{"body": json.dumps(array_of_success_messages)}]}
282+
expected_entry_counts = {
283+
"record_count": "100",
284+
"records_succeeded": None,
285+
"records_failed": None,
286+
}
255287

256288
response = lambda_handler(event=test_event, context={})
257289

@@ -268,6 +300,7 @@ def test_lambda_handler_updates_ack_file_but_does_not_mark_complete_when_records
268300
is_complete=False,
269301
)
270302
self.assert_audit_entry_status_equals(mock_batch_message_id, "Preprocessed")
303+
self.assert_audit_entry_counts_equal(mock_batch_message_id, expected_entry_counts)
271304

272305
def test_lambda_handler_updates_ack_file_and_marks_complete_when_all_records_processed(self):
273306
"""
@@ -305,6 +338,11 @@ def test_lambda_handler_updates_ack_file_and_marks_complete_when_all_records_pro
305338
all_messages_plus_eof = deepcopy(array_of_success_messages)
306339
all_messages_plus_eof.append(MOCK_MESSAGE_DETAILS.eof_message)
307340
test_event = {"Records": [{"body": json.dumps(all_messages_plus_eof)}]}
341+
expected_entry_counts = {
342+
"record_count": "100",
343+
"records_succeeded": "100",
344+
"records_failed": None,
345+
}
308346

309347
response = lambda_handler(event=test_event, context={})
310348

@@ -319,6 +357,61 @@ def test_lambda_handler_updates_ack_file_and_marks_complete_when_all_records_pro
319357
is_complete=True,
320358
)
321359
self.assert_audit_entry_status_equals(mock_batch_message_id, "Processed")
360+
self.assert_audit_entry_counts_equal(mock_batch_message_id, expected_entry_counts)
361+
362+
def test_lambda_handler_sets_records_succeeded(self):
363+
"""
364+
Test that the records_succeeded count is set when all records have been processed.
365+
"""
366+
mock_batch_message_id = "75db20e6-c0b5-4012-a8bc-f861a1dd4b22"
367+
368+
# Original source file had 100 records
369+
add_audit_entry_to_table(self.dynamodb_client, mock_batch_message_id, record_count=100)
370+
371+
# Previous invocations have already created and added to the temp ack file
372+
existing_ack_content = generate_sample_existing_ack_content()
373+
374+
self.s3_client.put_object(
375+
Bucket=BucketNames.DESTINATION,
376+
Key=MOCK_MESSAGE_DETAILS.temp_ack_file_key,
377+
Body=StringIO(existing_ack_content).getvalue(),
378+
)
379+
380+
array_of_success_messages = [
381+
{
382+
**BASE_SUCCESS_MESSAGE,
383+
"row_id": f"{mock_batch_message_id}^{i}",
384+
"imms_id": f"imms_{i}",
385+
"local_id": f"local^{i}",
386+
}
387+
for i in range(50, 75)
388+
]
389+
array_of_failure_messages = [
390+
{
391+
**BASE_FAILURE_MESSAGE,
392+
"row_id": f"{mock_batch_message_id}^{i}",
393+
"local_id": f"local^{i}",
394+
"diagnostics": DiagnosticsDictionaries.UNHANDLED_ERROR,
395+
}
396+
for i in range(75, 100)
397+
]
398+
399+
# Include the EoF message in the event
400+
array_of_messages = deepcopy(array_of_success_messages) + deepcopy(array_of_failure_messages)
401+
all_messages_plus_eof = array_of_messages
402+
all_messages_plus_eof.append(MOCK_MESSAGE_DETAILS.eof_message)
403+
test_event = {"Records": [{"body": json.dumps(all_messages_plus_eof)}]}
404+
expected_entry_counts = {
405+
"record_count": "100",
406+
"records_succeeded": "75",
407+
"records_failed": "25",
408+
}
409+
410+
response = lambda_handler(event=test_event, context={})
411+
412+
self.assertEqual(response, EXPECTED_ACK_LAMBDA_RESPONSE_FOR_SUCCESS)
413+
self.assert_audit_entry_status_equals(mock_batch_message_id, "Processed")
414+
self.assert_audit_entry_counts_equal(mock_batch_message_id, expected_entry_counts)
322415

323416
def test_lambda_handler_error_scenarios(self):
324417
"""Test that the lambda handler raises appropriate exceptions for malformed event data."""

lambdas/ack_backend/tests/test_splunk_logging.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ def test_splunk_logging_statuscode_diagnostics(
224224
with ( # noqa: E999
225225
patch("common.log_decorator.send_log_to_firehose") as mock_send_log_to_firehose, # noqa: E999
226226
patch("common.log_decorator.logger") as mock_logger, # noqa: E999
227+
patch("ack_processor.increment_records_failed_count") as mock_increment_records_failed_count, # noqa: E999
227228
): # noqa: E999
228229
result = lambda_handler(
229230
event=generate_event([{"diagnostics": test_case["diagnostics"]}]),
@@ -253,6 +254,7 @@ def test_splunk_logging_statuscode_diagnostics(
253254
call(self.stream_name, expected_second_logger_info_data),
254255
]
255256
)
257+
mock_increment_records_failed_count.assert_called()
256258

257259
def test_splunk_logging_multiple_rows(self):
258260
"""Tests logging for multiple objects in the body of the event"""
@@ -311,6 +313,7 @@ def test_splunk_logging_multiple_with_diagnostics(
311313
with ( # noqa: E999
312314
patch("common.log_decorator.send_log_to_firehose") as mock_send_log_to_firehose, # noqa: E999
313315
patch("common.log_decorator.logger") as mock_logger, # noqa: E999
316+
patch("ack_processor.increment_records_failed_count") as mock_increment_records_failed_count, # noqa: E999
314317
): # noqa: E999
315318
result = lambda_handler(generate_event(messages), context={})
316319

@@ -363,6 +366,7 @@ def test_splunk_logging_multiple_with_diagnostics(
363366
call(self.stream_name, expected_fourth_logger_info_data),
364367
]
365368
)
369+
mock_increment_records_failed_count.assert_called()
366370

367371
def test_splunk_update_ack_file_not_logged(self):
368372
"""Tests that update_ack_file is not logged if we have sent acks for less than the whole file"""
@@ -419,6 +423,7 @@ def test_splunk_update_ack_file_logged(self):
419423
patch(
420424
"update_ack_file.change_audit_table_status_to_processed"
421425
) as mock_change_audit_table_status_to_processed, # noqa: E999
426+
patch("update_ack_file.set_records_succeeded_count") as mock_set_records_succeeded_count, # noqa: E999
422427
): # noqa: E999
423428
result = lambda_handler(generate_event(messages, include_eof_message=True), context={})
424429

@@ -453,6 +458,7 @@ def test_splunk_update_ack_file_logged(self):
453458
]
454459
)
455460
mock_change_audit_table_status_to_processed.assert_called()
461+
mock_set_records_succeeded_count.assert_called()
456462

457463

458464
if __name__ == "__main__":

lambdas/ack_backend/tests/test_update_ack_file_flow.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ def setUp(self):
3939
self.mock_change_audit_status = self.change_audit_status_patcher.start()
4040
self.get_record_count_patcher = patch("update_ack_file.get_record_count_by_message_id")
4141
self.mock_get_record_count = self.get_record_count_patcher.start()
42+
self.set_records_succeeded_count_patcher = patch("update_ack_file.set_records_succeeded_count")
43+
self.mock_set_records_succeeded_count = self.set_records_succeeded_count_patcher.start()
4244

4345
def tearDown(self):
4446
self.logger_patcher.stop()
@@ -72,3 +74,4 @@ def test_audit_table_updated_correctly_when_ack_process_complete(self):
7274
# Assert: Only check audit table interactions
7375
self.mock_get_record_count.assert_called_once_with(message_id)
7476
self.mock_change_audit_status.assert_called_once_with(file_key, message_id)
77+
self.mock_set_records_succeeded_count.assert_called_once()

0 commit comments

Comments
 (0)