[server]: Add return_newest_data unit tests
This commit is contained in:
@ -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()
|
||||||
|
Reference in New Issue
Block a user