22
33from unittest import TestCase
44from unittest .mock import patch
5- from boto3 import resource as boto3_resource
5+ from boto3 import client as boto3_client
66from moto import mock_dynamodb
7- from errors import UnhandledAuditTableError
8- from clients import REGION_NAME
9- from tests .utils_for_tests .values_for_tests import MOCK_ENVIRONMENT_DICT
107
11- # Some environment variables are evaluated when constants and upsert_audit_table are imported,
12- # so environment dictionary must be mocked first
8+ from tests .utils_for_tests .mock_environment_variables import MOCK_ENVIRONMENT_DICT
9+ from tests .utils_for_tests .generic_setup_and_teardown import GenericSetUp , GenericTearDown
10+
11+ # Ensure environment variables are mocked before importing from src files
1312with patch .dict ("os.environ" , MOCK_ENVIRONMENT_DICT ):
14- from constants import AuditTableKeys , AUDIT_TABLE_NAME , AUDIT_TABLE_QUEUE_NAME_GSI , AUDIT_TABLE_FILENAME_GSI
13+ from constants import AUDIT_TABLE_NAME
1514 from audit_table import upsert_audit_table
15+ from errors import UnhandledAuditTableError
16+ from clients import REGION_NAME
17+
18+ dynamodb_client = boto3_client ("dynamodb" , region_name = REGION_NAME )
1619
1720
1821@mock_dynamodb
@@ -22,43 +25,16 @@ class TestAuditTable(TestCase):
2225
2326 def setUp (self ):
2427 """Set up test values to be used for the tests"""
25- self .dynamodb_resource = boto3_resource ("dynamodb" , region_name = REGION_NAME )
26- self .table = self .dynamodb_resource .create_table (
27- TableName = AUDIT_TABLE_NAME ,
28- KeySchema = [
29- {"AttributeName" : AuditTableKeys .MESSAGE_ID , "KeyType" : "HASH" },
30- # {"AttributeName": "placeholder", "KeyType": "RANGE"},
31- ],
32- AttributeDefinitions = [
33- {"AttributeName" : AuditTableKeys .MESSAGE_ID , "AttributeType" : "S" },
34- {"AttributeName" : AuditTableKeys .FILENAME , "AttributeType" : "S" },
35- {"AttributeName" : AuditTableKeys .QUEUE_NAME , "AttributeType" : "S" },
36- {"AttributeName" : AuditTableKeys .STATUS , "AttributeType" : "S" },
37- ],
38- ProvisionedThroughput = {"ReadCapacityUnits" : 5 , "WriteCapacityUnits" : 5 },
39- GlobalSecondaryIndexes = [
40- {
41- "IndexName" : AUDIT_TABLE_FILENAME_GSI ,
42- "KeySchema" : [{"AttributeName" : AuditTableKeys .FILENAME , "KeyType" : "HASH" }],
43- "Projection" : {"ProjectionType" : "KEYS_ONLY" },
44- "ProvisionedThroughput" : {"ReadCapacityUnits" : 5 , "WriteCapacityUnits" : 5 },
45- },
46- {
47- "IndexName" : AUDIT_TABLE_QUEUE_NAME_GSI ,
48- "KeySchema" : [
49- {"AttributeName" : AuditTableKeys .QUEUE_NAME , "KeyType" : "HASH" },
50- {"AttributeName" : AuditTableKeys .STATUS , "KeyType" : "RANGE" },
51- ],
52- "Projection" : {"ProjectionType" : "ALL" },
53- "ProvisionedThroughput" : {"ReadCapacityUnits" : 5 , "WriteCapacityUnits" : 5 },
54- },
55- ],
56- )
28+ GenericSetUp (dynamodb_client = dynamodb_client )
29+
30+ def tearDown (self ):
31+ """Tear down the test values"""
32+ GenericTearDown (dynamodb_client = dynamodb_client )
5733
58- assert self . table . table_status == "ACTIVE"
59- assert len ( self . table . global_secondary_indexes ) == 2
60- assert self . table . global_secondary_indexes [ 0 ][ "IndexName" ] == AUDIT_TABLE_FILENAME_GSI
61- assert self . table . global_secondary_indexes [ 1 ][ "IndexName" ] == AUDIT_TABLE_QUEUE_NAME_GSI
34+ @ staticmethod
35+ def get_table_items ():
36+ """Return all items in the audit table"""
37+ return dynamodb_client . scan ( TableName = AUDIT_TABLE_NAME ). get ( "Items" , [])
6238
6339 def test_upsert_audit_table (self ):
6440 """Test that the upsert_audit_table function works as expected for the following:
@@ -79,42 +55,42 @@ def test_upsert_audit_table(self):
7955
8056 # Test case 1: file_key_1 should be added to the audit table with status set to "Processing"
8157 expected_table_item_1 = {
82- "message_id" : message_id_1 ,
83- "filename" : file_key_1 ,
84- "queue_name" : " test_queue" ,
85- "status" : " Processing" ,
86- "timestamp" : created_at_formatted_string_1 ,
58+ "message_id" : { "S" : message_id_1 } ,
59+ "filename" : { "S" : file_key_1 } ,
60+ "queue_name" : { "S" : " test_queue"} ,
61+ "status" : { "S" : " Processing"} ,
62+ "timestamp" : { "S" : created_at_formatted_string_1 } ,
8763 }
8864
8965 # Test case 2: file_key_2 should be added to the audit table with status set to "Queued"
9066 expected_table_item_2 = {
91- "message_id" : message_id_2 ,
92- "filename" : file_key_2 ,
93- "queue_name" : " test_queue" ,
94- "status" : " Queued" ,
95- "timestamp" : created_at_formatted_string_2 ,
67+ "message_id" : { "S" : message_id_2 } ,
68+ "filename" : { "S" : file_key_2 } ,
69+ "queue_name" : { "S" : " test_queue"} ,
70+ "status" : { "S" : " Queued"} ,
71+ "timestamp" : { "S" : created_at_formatted_string_2 } ,
9672 }
9773
9874 # Test case 3: file_key_1 should be added to the audit table again,
9975 # with status set to "Not processed - duplicate"
10076 expected_table_item_3 = {
101- "message_id" : message_id_3 ,
102- "filename" : file_key_1 ,
103- "queue_name" : " test_queue" ,
104- "status" : " Not processed - duplicate" ,
105- "timestamp" : created_at_formatted_string_3 ,
77+ "message_id" : { "S" : message_id_3 } ,
78+ "filename" : { "S" : file_key_1 } ,
79+ "queue_name" : { "S" : " test_queue"} ,
80+ "status" : { "S" : " Not processed - duplicate"} ,
81+ "timestamp" : { "S" : created_at_formatted_string_3 } ,
10682 }
10783
10884 # Test case 4: file_key_4 should not be added to the audit table because the message_id is a duplicate.
10985 # Note that this scenario should never occur as a new unique message_id is generated for each file upload,
11086 # even if the file name is a duplicate, but this test is included for safety because default behaviour of
11187 # dynamodb is to overwrite the existing item if the message_id is the same.
112- expected_table_item_4 = { # This item should not be added to the table
113- "message_id" : message_id_3 ,
114- "filename" : file_key_4 ,
115- "queue_name" : " test_queue" ,
116- "status" : " Processed" ,
117- "timestamp" : created_at_formatted_string_4 ,
88+ expected_table_item_4 = {
89+ "message_id" : { "S" : message_id_3 } ,
90+ "filename" : { "S" : file_key_4 } ,
91+ "queue_name" : { "S" : " test_queue"} ,
92+ "status" : { "S" : " Processed"} ,
93+ "timestamp" : { "S" : created_at_formatted_string_4 } ,
11894 }
11995
12096 # Add a file to the audit table
@@ -128,7 +104,7 @@ def test_upsert_audit_table(self):
128104 is_existing_file = False ,
129105 )
130106 )
131- table_items = self .table . scan ()[ "Items" ]
107+ table_items = self .get_table_items ()
132108 assert len (table_items ) == 1
133109 assert expected_table_item_1 in table_items
134110
@@ -143,7 +119,7 @@ def test_upsert_audit_table(self):
143119 is_existing_file = False ,
144120 )
145121 )
146- table_items = self .table . scan ()[ "Items" ]
122+ table_items = self .get_table_items ()
147123 assert len (table_items ) == 2
148124 assert expected_table_item_1 in table_items
149125 assert expected_table_item_2 in table_items
@@ -162,7 +138,7 @@ def test_upsert_audit_table(self):
162138
163139 # Check that the file has been added to the audit table again,
164140 # with the different message_id and created_at_formatted_string
165- table_items = self .table . scan ()[ "Items" ]
141+ table_items = self .get_table_items ()
166142 assert len (table_items ) == 3
167143 assert expected_table_item_1 in table_items
168144 assert expected_table_item_2 in table_items
@@ -180,7 +156,7 @@ def test_upsert_audit_table(self):
180156 )
181157
182158 # Check that the file has not been added to the audit table
183- table_items = self .table . scan ()[ "Items" ]
159+ table_items = self .get_table_items ()
184160 assert len (table_items ) == 3
185161 assert expected_table_item_1 in table_items
186162 assert expected_table_item_2 in table_items
0 commit comments