[server]: Add return_newest_data unit tests

This commit is contained in:
2025-03-09 23:26:22 +00:00
parent 567ac09d12
commit f1232ccad6

View File

@ -2,108 +2,118 @@ import unittest
from unittest.mock import patch, MagicMock from unittest.mock import patch, MagicMock
import json import json
import os import os
# Mock environment variable BEFORE importing lambda_handler
os.environ['TABLE_NAME'] = 'mock_table'
from functions.return_newest_data.lambda_function import lambda_handler from functions.return_newest_data.lambda_function import lambda_handler
from boto3.dynamodb.conditions import Attr
from botocore.exceptions import ClientError
class TestLambdaFunction(unittest.TestCase): class TestLambdaFunction(unittest.TestCase):
@patch('src.functions.return_newest_data.lambda_function.boto3.resource') # Mock environment variable before each test
def test_single_object_type(self, mock_boto_resource): def setUp(self):
mock_table = MagicMock() patch.dict(os.environ, {'TABLE_NAME': 'test-table'}).start()
mock_boto_resource.return_value.Table.return_value = mock_table
# Mock scan response for single object type with pagination # Clean up patches after each test
def mock_scan(**kwargs): def tearDown(self):
if 'FilterExpression' in kwargs: patch.stopall()
filter_expr = kwargs['FilterExpression']
if 'objectType' in str(filter_expr):
return {'Items': [{'objectType': 'type1', 'timestamp': '1234567890'}]}
elif 'timestamp' in str(filter_expr):
return {'Items': [{'objectType': 'type1', 'timestamp': '1234567890'}]}
# Simulate pagination
if 'ExclusiveStartKey' in kwargs:
return {'Items': [], 'LastEvaluatedKey': None}
return {'Items': [{'timestamp': '1234567890'}], 'LastEvaluatedKey': {'dummy_key': 'dummy_value'}}
mock_table.scan.side_effect = mock_scan @patch('functions.return_newest_data.lambda_function.dynamodb.Table')
def test_lambda_handler_with_object_type(self, mock_table):
# Mock scan responses for timestamps
mock_table.return_value.scan.side_effect = [
{'Items': [{'timestamp': '1234567890'}, {'timestamp': '1234567891'}]}, # First scan for timestamps
{'Items': [{'objectID': '1', 'objectType': 'Bus', 'timestamp': '1234567891'}]} # Fetch latest items
]
event = {'queryStringParameters': {'objectType': 'type1'}} # Mock event with objectType query parameter
context = {} event = {
'queryStringParameters': {
'objectType': 'Bus'
}
}
response = lambda_handler(event, context) result = lambda_handler(event, {})
self.assertEqual(result['statusCode'], 200)
print("test_single_object_type - Status Code:", response['statusCode']) # Parse result body
print("Response Body:", response['body']) body = json.loads(result['body'])
self.assertEqual(len(body), 1)
self.assertEqual(body[0]['objectType'], 'Bus')
self.assertEqual(response['statusCode'], 200) @patch('functions.return_newest_data.lambda_function.dynamodb.Table')
self.assertEqual(json.loads(response['body']), [{'objectType': 'type1', 'timestamp': '1234567890'}]) def test_lambda_handler_without_object_type(self, mock_table):
# Mock scan responses for timestamps and data
mock_table.return_value.scan.side_effect = [
{'Items': [{'timestamp': '1234567890'}, {'timestamp': '1234567891'}]}, # First scan for timestamps
{'Items': [{'objectID': '1', 'objectType': 'Bus', 'timestamp': '1234567891'}]} # Fetch latest items
]
@patch('src.functions.return_newest_data.lambda_function.boto3.resource') # Mock event without objectType query parameter
def test_multiple_object_types(self, mock_boto_resource): event = {
mock_table = MagicMock() 'queryStringParameters': None
mock_boto_resource.return_value.Table.return_value = mock_table }
# Mock scan response for multiple object types with pagination result = lambda_handler(event, {})
def mock_scan(**kwargs): self.assertEqual(result['statusCode'], 200)
if 'FilterExpression' in kwargs:
filter_expr = kwargs['FilterExpression']
if 'objectType' in str(filter_expr):
return {'Items': [
{'objectType': 'type1', 'timestamp': '1234567891'},
{'objectType': 'type2', 'timestamp': '1234567891'}
]}
elif 'timestamp' in str(filter_expr):
return {'Items': [
{'objectType': 'type1', 'timestamp': '1234567891'},
{'objectType': 'type2', 'timestamp': '1234567891'}
]}
# Simulate pagination
if 'ExclusiveStartKey' in kwargs:
return {'Items': [], 'LastEvaluatedKey': None}
return {'Items': [{'timestamp': '1234567891'}], 'LastEvaluatedKey': {'dummy_key': 'dummy_value'}}
mock_table.scan.side_effect = mock_scan # Parse result body
body = json.loads(result['body'])
self.assertEqual(len(body), 1)
self.assertEqual(body[0]['objectType'], 'Bus')
event = {'queryStringParameters': {'objectType': 'type1,type2'}} @patch('functions.return_newest_data.lambda_function.dynamodb.Table')
context = {} def test_lambda_handler_with_pagination(self, mock_table):
# Mock paginated scan responses for timestamps and data
mock_table.return_value.scan.side_effect = [
{'Items': [{'timestamp': '1234567890'}], 'LastEvaluatedKey': 'key1'},
{'Items': [{'timestamp': '1234567891'}]}, # Last page for timestamps
{'Items': [{'objectID': '1', 'objectType': 'Bus', 'timestamp': '1234567891'}], 'LastEvaluatedKey': 'key2'},
{'Items': [{'objectID': '2', 'objectType': 'Train', 'timestamp': '1234567891'}]} # Last page for data
]
response = lambda_handler(event, context) event = {
'queryStringParameters': {
'objectType': 'Bus,Train'
}
}
print("test_multiple_object_types - Status Code:", response['statusCode']) result = lambda_handler(event, {})
print("Response Body:", response['body']) self.assertEqual(result['statusCode'], 200)
self.assertEqual(response['statusCode'], 200) body = json.loads(result['body'])
self.assertEqual(json.loads(response['body']), [ self.assertEqual(len(body), 2)
{'objectType': 'type1', 'timestamp': '1234567891'}, self.assertEqual(body[0]['objectType'], 'Bus')
{'objectType': 'type2', 'timestamp': '1234567891'} self.assertEqual(body[1]['objectType'], 'Train')
])
@patch('src.functions.return_newest_data.lambda_function.boto3.resource') @patch('functions.return_newest_data.lambda_function.dynamodb.Table')
def test_exception_handling(self, mock_boto_resource): def test_lambda_handler_no_data(self, mock_table):
mock_table = MagicMock() # Mock empty scan response
mock_boto_resource.return_value.Table.return_value = mock_table mock_table.return_value.scan.return_value = {'Items': []}
# Mock scan to raise a ResourceNotFoundException event = {
mock_table.scan.side_effect = ClientError( 'queryStringParameters': None
{"Error": {"Code": "ResourceNotFoundException", "Message": "Requested resource not found"}}, }
"Scan"
)
event = {'queryStringParameters': {'objectType': 'type1'}} result = lambda_handler(event, {})
context = {} self.assertEqual(result['statusCode'], 200)
response = lambda_handler(event, context) body = json.loads(result['body'])
self.assertEqual(len(body), 0)
print("test_exception_handling - Status Code:", response['statusCode']) @patch('functions.return_newest_data.lambda_function.dynamodb.Table')
print("Response Body:", response['body']) def test_lambda_handler_error(self, mock_table):
# Mock table scan to raise an exception
mock_table.return_value.scan.side_effect = Exception('DynamoDB error')
self.assertEqual(response['statusCode'], 500) event = {
self.assertIn('Requested resource not found', json.loads(response['body'])['error']) 'queryStringParameters': None
}
if __name__ == '__main__': result = lambda_handler(event, {})
self.assertEqual(result['statusCode'], 500)
body = json.loads(result['body'])
self.assertIn('error', body)
self.assertEqual(body['error'], 'DynamoDB error')
if __name__ == "__main__":
unittest.main() unittest.main()