"""Test cache manager handlers.""" import json from unittest.mock import Mock from unittest.mock import patch import pytest from cache_manager import handlers from cache_manager import message_validator from cache_manager import response def test_dispatch(monkeypatch): """Test dispatch function.""" expected = Mock() # Mocking handler valid_action_mock = Mock(return_value=expected) # Patching VALID_ACTIONS monkeypatch.setattr( handlers, 'VALID_ACTIONS', {'do-something': valid_action_mock}) # Dummy payload payload = dict(action='do-something') result = handlers.dispatch(payload) # Asserts assert result == expected valid_action_mock.assert_called_once_with(payload) def test_dispatch_with_invalid_action(monkeypatch): """Test dispatch function with an invalid action.""" expected = Mock() default_action_mock = Mock(return_value=expected) monkeypatch.setattr(handlers, 'VALID_ACTIONS', {}) monkeypatch.setattr(handlers, 'default_action', default_action_mock) # Dummy payload payload = dict(action='do-whatever') result = handlers.dispatch(payload) # Asserts assert result == expected default_action_mock.assert_called_once_with(payload) def test_default_action(monkeypatch): """Test default action.""" # Mocking response.create_error_response function error_response_mock = Mock() monkeypatch.setattr( handlers.response, 'create_error_response', error_response_mock) handlers.default_action(dict()) # Asserts error_response_mock.assert_called_once_with( 'Invalid Cache Manager action.') @patch('cache_manager.response.Response') def test_drop_cache_action(response_class_mock, monkeypatch): """Test drop_cache_action.""" expected_num_deleted = 5 upcs = ['123', '456'] source = 'test-source' response_class_mock.return_value = Mock( message='{} dropped {}'.format(source, expected_num_deleted), status=response.OK) # Mocking handlers.cache.delete_upcs function delete_upcs_mock = Mock(return_value=expected_num_deleted) monkeypatch.setattr(handlers.cache, 'delete_upcs', delete_upcs_mock) payload = dict(source=source, upcs=upcs) result = handlers.drop_cache_action(payload) # Asserts assert result.status == response.OK assert response_class_mock.called delete_upcs_mock.assert_called_once_with(*upcs) assert 'dropped {}'.format(expected_num_deleted) in result.message assert payload.get('source') in result.message def get_valid_response(): """Build a valid response mock. Returns: Mock: mock of a validation Response object. """ return Mock(message='', __bool__=Mock(return_value=True)) def get_invalid_response(): """Build an invalid response mock. Returns: Mock: mock of an validation Response object with errors. """ return Mock(message='invalid payload', status=response.WARNING, __bool__=Mock(return_value=False)) def get_ok_dispatch_response(): """Build an OK dispatch response mock. Returns: Mock: mock of a dispatch Response object without errors. """ return Mock(message='All done', error=None, status=response.OK) def get_error_dispatch_response(error=Exception('Some error...')): """Build an OK dispatch response mock. Args: error (Exception): error object. Returns: Mock: mock of a dispatch Response object with errors. """ return Mock( message='Some error happened', error=error, status=response.ERROR) @pytest.mark.parametrize('valid_message,expected', [ (get_invalid_response(), get_invalid_response()), (get_valid_response(), get_ok_dispatch_response()), ]) def test_process(valid_message, expected, monkeypatch): """Test process function. Cases covered are: - message validation fails, WARNING returned. - validation OK and handler OK Args: valid_message (bool): whether or not the message is valid. Used as return value of the validate_message function. expected (tuple): expected result. Used as return value of the dispatch function. """ # Mocking # message message_mock = Mock(body='{"hello": "there"}') # handlers.cache.delete_upcs function validate_message_mock = Mock(return_value=valid_message) monkeypatch.setattr( message_validator, 'validate_message', validate_message_mock) # handlers.dispatch function dispatch_mock = Mock(return_value=expected) monkeypatch.setattr(handlers, 'dispatch', dispatch_mock) result = handlers.process(message_mock) # Asserts validate_message_mock.assert_called_once_with(message_mock) if valid_message: dispatch_mock.assert_called_once_with(json.loads(message_mock.body)) assert expected.status == result.status assert expected.message == result.message def test_process_with_error(monkeypatch): """Test process function with errors during processing.""" # Error to be triggered error = Exception('Some error happened') # Mocking # message message_mock = Mock(body='{"hello": "there"}') # handlers.cache.delete_upcs function validate_message_mock = Mock(return_value=get_valid_response()) monkeypatch.setattr( message_validator, 'validate_message', validate_message_mock) # handlers.dispatch function dispatch_mock = Mock(side_effect=error) monkeypatch.setattr(handlers, 'dispatch', dispatch_mock) # response.create_error_response function dispatch_error_mock = get_error_dispatch_response(error) monkeypatch.setattr( handlers.response, 'create_error_response', Mock(return_value=dispatch_error_mock)) result = handlers.process(message_mock) # Asserts validate_message_mock.assert_called_once_with(message_mock) dispatch_mock.assert_called_once_with(json.loads(message_mock.body)) assert result.status == dispatch_error_mock.status assert result.message == str(dispatch_error_mock.error)