"""Unit tests for common module for streams totals lambda functions.""" import mock import pytest import consts # noqa import streams_totals @pytest.fixture(params=[consts.VENDOR, consts.TRACK]) def totals_type(request): """Total values type fixture.""" return request.param @pytest.fixture(params=[consts.SPOTIFY, consts.APPLE_MUSIC]) def store_type(request): """Total store type fixture.""" return request.param @pytest.fixture(name='models_mock') def get_models_mock(monkeypatch): """Mock the models for Track and Vendor.""" models_mock = mock.MagicMock() monkeypatch.setattr( 'sosmodels.streams_vendor_totals.StreamsVendorTotalsSpotify', models_mock.StreamsVendorTotalsSpotify) monkeypatch.setattr( 'sosmodels.streams_vendor_totals.StreamsVendorTotalsAppleMusic', models_mock.StreamsVendorTotalsAppleMusic) monkeypatch.setattr( 'sosmodels.streams_track_totals.StreamsTrackTotalsSpotify', models_mock.StreamsTrackTotalsSpotify) monkeypatch.setattr( 'sosmodels.streams_track_totals.StreamsTrackTotalsAppleMusic', models_mock.StreamsTrackTotalsAppleMusic) return { consts.VENDOR: { consts.SPOTIFY: models_mock.StreamsVendorTotalsSpotify, consts.APPLE_MUSIC: models_mock.StreamsVendorTotalsAppleMusic, }, consts.TRACK: { consts.SPOTIFY: models_mock.StreamsTrackTotalsSpotify, consts.APPLE_MUSIC: models_mock.StreamsTrackTotalsAppleMusic, } } @mock.patch('smart_open.smart_open') def test_load(smart_open_mock, models_mock, totals_type, store_type): """Test load function.""" # mocking processing_data = ['v1,2,v3,0,0,0,0', 'v4,5,v7,1,2,3,4'] rows_amount = len(processing_data) fake_url = 's3://{}/file'.format(store_type) totals_model_mock = models_mock[totals_type][store_type] batch_write_mock = mock.Mock() batch_write_context_manager_mock = mock.Mock() totals_model_mock.batch_write.return_value = ( batch_write_context_manager_mock) batch_write_enter_mock = mock.Mock() batch_write_enter_mock.return_value = batch_write_mock batch_write_exit_mock = mock.Mock() batch_write_context_manager_mock.__enter__ = batch_write_enter_mock batch_write_context_manager_mock.__exit__ = batch_write_exit_mock context_manager_mock = mock.Mock() smart_open_mock.return_value = context_manager_mock enter_mock = mock.Mock() enter_mock.return_value = processing_data batch_write_exit_mock = mock.Mock() context_manager_mock.__enter__ = enter_mock context_manager_mock.__exit__ = batch_write_exit_mock item_mock = mock.Mock() totals_model_mock.side_effect = ( [item_mock] * len(processing_data)) hash_key_column = ( 'vendor_key' if totals_type == consts.VENDOR else 'vendor_track_key') columns = [ 'date', 'ttl', hash_key_column, 'overall_number_of_streams', 'streams_from_passive_discovery', 'streams_from_active_discovery', 'streams_from_collection'] attribute_mock = mock.Mock() attribute_mock.deserialize.side_effect = [ int(value) if value.isdigit() else value for row in processing_data for value in row.split(',')] for attribute in columns: setattr(totals_model_mock, attribute, attribute_mock) # test function mock.call streams_totals.load(fake_url, totals_type) # checking smart_open_mock.assert_called_once_with(fake_url) for row in processing_data: item_data = dict( zip(columns, [value for value in row.split(',')])) item = { hash_key_column: item_data[hash_key_column], 'date': item_data['date'], 'ttl': int(item_data['ttl']), 'overall_number_of_streams': int( item_data['overall_number_of_streams']), 'streams_from_passive_discovery': int( item_data['streams_from_passive_discovery']), 'streams_from_active_discovery': int( item_data['streams_from_active_discovery']), 'streams_from_collection': int( item_data['streams_from_collection']), } totals_model_mock.assert_any_call(**item) batch_write_mock.save.assert_has_calls( [mock.call(item_mock)] * rows_amount) def test_load_fail(): """Test load function fail.""" with pytest.raises(KeyError): streams_totals.load('s3://fake_url', 'incorrect type') @mock.patch('smart_open.smart_open') def test_deletion(smart_open_mock, totals_type, store_type, models_mock): """Test delete function.""" totals_model_mock = models_mock[totals_type][store_type] fake_models = [mock.MagicMock() for _ in range(5)] totals_model_mock.batch_get.return_value = fake_models fake_url = 's3://{}/{}/file'.format(totals_type, store_type) streams_totals.delete(fake_url) totals_model_mock.batch_get.assert_called_once() for model in fake_models: model.delete.assert_called_once() def test_deletion_fails(): """Test delete function fails to .""" with pytest.raises(KeyError): streams_totals.delete('s3://invalid_file_path')