def test_publish_to_queue(empty_config, maybe_declare, patch_publisher): container = Mock(spec=ServiceContainer) container.shared_extensions = {} container.service_name = "srcservice" container.config = empty_config ctx_data = {"language": "en"} service = Mock() worker_ctx = WorkerContext(container, service, DummyProvider("publish"), data=ctx_data) publisher = Publisher(queue=foobar_queue).bind(container, "publish") producer = Mock() connection = Mock() get_connection, get_producer = patch_publisher(publisher) get_connection.return_value = as_context_manager(connection) get_producer.return_value = as_context_manager(producer) # test declarations publisher.setup() maybe_declare.assert_called_once_with(foobar_queue, connection) # test publish msg = "msg" headers = {"nameko.language": "en", "nameko.call_id_stack": ["srcservice.publish.0"]} service.publish = publisher.get_dependency(worker_ctx) service.publish(msg, publish_kwarg="value") producer.publish.assert_called_once_with( msg, headers=headers, exchange=foobar_ex, retry=True, retry_policy=DEFAULT_RETRY_POLICY, publish_kwarg="value" )
def test_declare(self, mock_container, producer): """ Declarations provided at publish time are merged with any provided at instantiation time. Any provided exchange and queue are always declared. """ mock_container.config = { 'AMQP_URI': 'memory://localhost' } mock_container.service_name = "service" worker_ctx = Mock() worker_ctx.context_data = {} exchange = Mock() instantiation_value = [Mock()] publish_value = [Mock()] publisher = Publisher( exchange=exchange, **{'declare': instantiation_value} ).bind(mock_container, "publish") publisher.setup() publish = publisher.get_dependency(worker_ctx) publish("payload") assert producer.publish.call_args[1]['declare'] == ( instantiation_value + [exchange] ) publish("payload", declare=publish_value) assert producer.publish.call_args[1]['declare'] == ( instantiation_value + [exchange] + publish_value )
def test_unserialisable_headers(rabbit_manager, rabbit_config, mock_container): vhost = rabbit_config['vhost'] container = mock_container container.service_name = "service" container.config = rabbit_config container.spawn_managed_thread = eventlet.spawn ctx_data = {'language': 'en', 'customheader': None} service = Mock() worker_ctx = WorkerContext( container, service, DummyProvider('method'), data=ctx_data ) publisher = Publisher( exchange=foobar_ex, queue=foobar_queue).bind(container, "publish") publisher.setup() publisher.start() service.publish = publisher.get_dependency(worker_ctx) service.publish("msg") messages = rabbit_manager.get_messages(vhost, foobar_queue.name) assert messages[0]['properties']['headers'] == { 'nameko.language': 'en', 'nameko.call_id_stack': ['service.method.0'], # no `customheader` }
def test_use_confirms(self, mock_container, get_producer): """ Verify that publish-confirms can be set as a default specified at instantiation time, which can be overriden by a value specified at publish time. """ mock_container.config = {'AMQP_URI': 'memory://localhost'} mock_container.service_name = "service" worker_ctx = Mock() worker_ctx.context_data = {} publisher = Publisher( use_confirms=False ).bind(mock_container, "publish") publisher.setup() publish = publisher.get_dependency(worker_ctx) publish("payload") use_confirms = get_producer.call_args[0][3].get('confirm_publish') assert use_confirms is False publish("payload", use_confirms=True) use_confirms = get_producer.call_args[0][3].get('confirm_publish') assert use_confirms is True
def test_use_confirms(self, mock_container, get_producer): """ Verify that publish-confirms can be set as a default specified at instantiation time, which can be overriden by a value specified at publish time. """ mock_container.config = {'AMQP_URI': 'memory://localhost'} mock_container.service_name = "service" worker_ctx = Mock() worker_ctx.context_data = {} publisher = Publisher( use_confirms=False ).bind(mock_container, "publish") publisher.setup() publish = publisher.get_dependency(worker_ctx) publish("payload") (_, use_confirms, _), _ = get_producer.call_args assert use_confirms is False publish("payload", use_confirms=True) (_, use_confirms, _), _ = get_producer.call_args assert use_confirms is True
def test_unserialisable_headers(rabbit_manager, rabbit_config, mock_container): vhost = rabbit_config['vhost'] container = mock_container container.service_name = "service" container.config = rabbit_config container.spawn_managed_thread = eventlet.spawn ctx_data = {'language': 'en', 'customheader': None} service = Mock() worker_ctx = WorkerContext( container, service, DummyProvider('method'), data=ctx_data ) publisher = Publisher( exchange=foobar_ex, declare=[foobar_queue]).bind(container, "publish") publisher.setup() publisher.start() with pytest.warns(UserWarning): service.publish = publisher.get_dependency(worker_ctx) service.publish("msg") messages = rabbit_manager.get_messages(vhost, foobar_queue.name) assert messages[0]['properties']['headers'] == { 'nameko.language': 'en', 'nameko.call_id_stack': ['service.method.0'], # no `customheader` }
def test_declare(self, mock_container, producer): """ Declarations provided at publish time are merged with any provided at instantiation time. Any provided exchange and queue are always declared. """ mock_container.config = { 'AMQP_URI': 'memory://localhost' } mock_container.service_name = "service" worker_ctx = Mock() worker_ctx.context_data = {} exchange = Mock() queue = Mock() instantiation_value = [Mock()] publish_value = [Mock()] publisher = Publisher( exchange=exchange, queue=queue, **{'declare': instantiation_value} ).bind(mock_container, "publish") publisher.setup() publish = publisher.get_dependency(worker_ctx) publish("payload") assert producer.publish.call_args[1]['declare'] == ( instantiation_value + [exchange, queue] ) publish("payload", declare=publish_value) assert producer.publish.call_args[1]['declare'] == ( instantiation_value + [exchange, queue] + publish_value )
def test_regular_parameters( self, parameter, mock_container, producer ): """ Verify that most parameters can be specified at instantiation time, and overriden at publish time. """ mock_container.config = {'AMQP_URI': 'memory://localhost'} mock_container.service_name = "service" worker_ctx = Mock() worker_ctx.context_data = {} instantiation_value = Mock() publish_value = Mock() publisher = Publisher( **{parameter: instantiation_value} ).bind(mock_container, "publish") publisher.setup() publish = publisher.get_dependency(worker_ctx) publish("payload") assert producer.publish.call_args[1][parameter] == instantiation_value publish("payload", **{parameter: publish_value}) assert producer.publish.call_args[1][parameter] == publish_value
def test_unserialisable_headers(rabbit_manager, rabbit_config): vhost = rabbit_config["vhost"] container = Mock(spec=ServiceContainer) container.service_name = "service" container.config = rabbit_config container.spawn_managed_thread = eventlet.spawn ctx_data = {"language": "en", "customheader": None} service = Mock() worker_ctx = CustomWorkerContext(container, service, DummyProvider("method"), data=ctx_data) publisher = Publisher(exchange=foobar_ex, queue=foobar_queue).bind(container, "publish") publisher.setup() publisher.start() service.publish = publisher.get_dependency(worker_ctx) service.publish("msg") messages = rabbit_manager.get_messages(vhost, foobar_queue.name) assert messages[0]["properties"]["headers"] == { "nameko.language": "en", "nameko.call_id_stack": ["service.method.0"], # no `customheader` }
def test_publish_custom_headers( mock_container, maybe_declare, mock_producer, mock_connection, rabbit_config ): container = mock_container container.config = rabbit_config container.service_name = "srcservice" ctx_data = {'language': 'en', 'customheader': 'customvalue'} service = Mock() worker_ctx = WorkerContext( container, service, DummyProvider('method'), data=ctx_data ) publisher = Publisher(queue=foobar_queue).bind(container, "publish") # test declarations publisher.setup() maybe_declare.assert_called_once_with(foobar_queue, mock_connection) # test publish msg = "msg" headers = {'nameko.language': 'en', 'nameko.customheader': 'customvalue', 'nameko.call_id_stack': ['srcservice.method.0']} service.publish = publisher.get_dependency(worker_ctx) service.publish(msg, publish_kwarg="value") mock_producer.publish.assert_called_once_with( msg, headers=headers, exchange=foobar_ex, retry=True, serializer=container.serializer, mandatory=False, retry_policy=DEFAULT_RETRY_POLICY, publish_kwarg="value")
def test_publish_to_exchange(maybe_declare, patch_publisher, mock_container): container = mock_container container.service_name = "srcservice" service = Mock() worker_ctx = WorkerContext(container, service, DummyProvider("publish")) publisher = Publisher(exchange=foobar_ex).bind(container, "publish") producer = Mock() connection = Mock() get_connection, get_producer = patch_publisher(publisher) get_connection.return_value = as_context_manager(connection) get_producer.return_value = as_context_manager(producer) # test declarations publisher.setup() maybe_declare.assert_called_once_with(foobar_ex, connection) # test publish msg = "msg" service.publish = publisher.get_dependency(worker_ctx) service.publish(msg, publish_kwarg="value") headers = { 'nameko.call_id_stack': ['srcservice.publish.0'] } producer.publish.assert_called_once_with( msg, headers=headers, exchange=foobar_ex, retry=True, serializer=container.serializer, retry_policy=DEFAULT_RETRY_POLICY, publish_kwarg="value")
def test_publish_to_queue(patch_maybe_declare, mock_producer, mock_connection, mock_container): container = mock_container container.config = {'AMQP_URI': 'memory://'} container.shared_extensions = {} container.service_name = "srcservice" ctx_data = {'language': 'en'} service = Mock() worker_ctx = WorkerContext(container, service, DummyProvider("publish"), data=ctx_data) publisher = Publisher(queue=foobar_queue).bind(container, "publish") # test declarations publisher.setup() assert patch_maybe_declare.call_args_list == [ call(foobar_queue, mock_connection) ] # test publish msg = "msg" headers = { 'nameko.language': 'en', 'nameko.call_id_stack': ['srcservice.publish.0'], } service.publish = publisher.get_dependency(worker_ctx) service.publish(msg, publish_kwarg="value") expected_args = ('msg', ) expected_kwargs = { 'publish_kwarg': "value", 'exchange': foobar_ex, 'headers': headers, 'declare': publisher.declare, 'retry': publisher.publisher_cls.retry, 'retry_policy': publisher.publisher_cls.retry_policy, 'compression': publisher.publisher_cls.compression, 'mandatory': publisher.publisher_cls.mandatory, 'expiration': publisher.publisher_cls.expiration, 'delivery_mode': publisher.publisher_cls.delivery_mode, 'priority': publisher.publisher_cls.priority, 'serializer': publisher.serializer } assert mock_producer.publish.call_args_list == [ call(*expected_args, **expected_kwargs) ]
def test_publish_to_queue( patch_maybe_declare, mock_producer, mock_channel, mock_container ): container = mock_container container.config = {'AMQP_URI': 'memory://'} container.shared_extensions = {} container.service_name = "srcservice" ctx_data = {'language': 'en'} service = Mock() worker_ctx = WorkerContext( container, service, DummyProvider("publish"), data=ctx_data) publisher = Publisher(queue=foobar_queue).bind(container, "publish") # test declarations publisher.setup() assert patch_maybe_declare.call_args_list == [ call(foobar_queue, mock_channel) ] # test publish msg = "msg" headers = { 'nameko.language': 'en', 'nameko.call_id_stack': ['srcservice.publish.0'], } service.publish = publisher.get_dependency(worker_ctx) service.publish(msg, publish_kwarg="value") expected_args = ('msg',) expected_kwargs = { 'publish_kwarg': "value", 'exchange': foobar_ex, 'headers': headers, 'declare': publisher.declare, 'retry': publisher.publisher_cls.retry, 'retry_policy': publisher.publisher_cls.retry_policy, 'compression': publisher.publisher_cls.compression, 'mandatory': publisher.publisher_cls.mandatory, 'expiration': publisher.publisher_cls.expiration, 'delivery_mode': publisher.publisher_cls.delivery_mode, 'priority': publisher.publisher_cls.priority, 'serializer': publisher.serializer } assert mock_producer.publish.call_args_list == [ call(*expected_args, **expected_kwargs) ]
def test_headers(self, mock_container, producer): """ Headers provided at publish time are merged with any provided at instantiation time. Nameko headers are always present. """ mock_container.config = { 'AMQP_URI': 'memory://localhost' } mock_container.service_name = "service" # use a real worker context so nameko headers are generated service = Mock() entrypoint = Mock(method_name="method") worker_ctx = WorkerContext( mock_container, service, entrypoint, data={'context': 'data'} ) nameko_headers = { 'nameko.context': 'data', 'nameko.call_id_stack': ['service.method.0'], } instantiation_value = {'foo': Mock()} publish_value = {'bar': Mock()} publisher = Publisher( **{'headers': instantiation_value} ).bind(mock_container, "publish") publisher.setup() publish = publisher.get_dependency(worker_ctx) def merge_dicts(base, *updates): merged = base.copy() [merged.update(update) for update in updates] return merged publish("payload") assert producer.publish.call_args[1]['headers'] == merge_dicts( nameko_headers, instantiation_value ) publish("payload", headers=publish_value) assert producer.publish.call_args[1]['headers'] == merge_dicts( nameko_headers, instantiation_value, publish_value )
def test_publish_custom_headers(mock_container, mock_producer, mock_connection, rabbit_config): container = mock_container container.config = rabbit_config container.service_name = "srcservice" ctx_data = {'language': 'en', 'customheader': 'customvalue'} service = Mock() worker_ctx = WorkerContext(container, service, DummyProvider('method'), data=ctx_data) publisher = Publisher(queue=foobar_queue).bind(container, "publish") publisher.setup() # test publish msg = "msg" headers = { 'nameko.language': 'en', 'nameko.customheader': 'customvalue', 'nameko.call_id_stack': ['srcservice.method.0'] } service.publish = publisher.get_dependency(worker_ctx) service.publish(msg, publish_kwarg="value") expected_args = ('msg', ) expected_kwargs = { 'publish_kwarg': "value", 'exchange': foobar_ex, 'headers': headers, 'declare': publisher.declare, 'retry': publisher.publisher_cls.retry, 'retry_policy': publisher.publisher_cls.retry_policy, 'compression': publisher.publisher_cls.compression, 'mandatory': publisher.publisher_cls.mandatory, 'expiration': publisher.publisher_cls.expiration, 'delivery_mode': publisher.publisher_cls.delivery_mode, 'priority': publisher.publisher_cls.priority, 'serializer': publisher.serializer } assert mock_producer.publish.call_args_list == [ call(*expected_args, **expected_kwargs) ]
def test_publish_to_rabbit(rabbit_manager, rabbit_config, mock_container): vhost = rabbit_config['vhost'] container = mock_container container.service_name = "service" container.config = rabbit_config ctx_data = {'language': 'en', 'customheader': 'customvalue'} service = Mock() worker_ctx = WorkerContext( container, service, DummyProvider('method'), data=ctx_data ) publisher = Publisher( exchange=foobar_ex, declare=[foobar_queue] ).bind(container, "publish") publisher.setup() publisher.start() # test queue, exchange and binding created in rabbit exchanges = rabbit_manager.get_exchanges(vhost) queues = rabbit_manager.get_queues(vhost) bindings = rabbit_manager.get_queue_bindings(vhost, foobar_queue.name) assert "foobar_ex" in [exchange['name'] for exchange in exchanges] assert "foobar_queue" in [queue['name'] for queue in queues] assert "foobar_ex" in [binding['source'] for binding in bindings] service.publish = publisher.get_dependency(worker_ctx) service.publish("msg") # test message published to queue messages = rabbit_manager.get_messages(vhost, foobar_queue.name) assert ['"msg"'] == [msg['payload'] for msg in messages] # test message headers assert messages[0]['properties']['headers'] == { 'nameko.language': 'en', 'nameko.customheader': 'customvalue', 'nameko.call_id_stack': ['service.method.0'], }
def test_publish_custom_headers( mock_container, mock_producer, rabbit_config ): container = mock_container container.config = rabbit_config container.service_name = "srcservice" ctx_data = {'language': 'en', 'customheader': 'customvalue'} service = Mock() worker_ctx = WorkerContext( container, service, DummyProvider('method'), data=ctx_data ) publisher = Publisher(exchange=foobar_ex).bind(container, "publish") publisher.setup() # test publish msg = "msg" headers = {'nameko.language': 'en', 'nameko.customheader': 'customvalue', 'nameko.call_id_stack': ['srcservice.method.0']} service.publish = publisher.get_dependency(worker_ctx) service.publish(msg, publish_kwarg="value") expected_args = ('msg',) expected_kwargs = { 'publish_kwarg': "value", 'exchange': foobar_ex, 'headers': headers, 'declare': publisher.declare, 'retry': publisher.publisher_cls.retry, 'retry_policy': publisher.publisher_cls.retry_policy, 'compression': publisher.publisher_cls.compression, 'mandatory': publisher.publisher_cls.mandatory, 'expiration': publisher.publisher_cls.expiration, 'delivery_mode': publisher.publisher_cls.delivery_mode, 'priority': publisher.publisher_cls.priority, 'serializer': publisher.serializer } assert mock_producer.publish.call_args_list == [ call(*expected_args, **expected_kwargs) ]
def test_publish_to_rabbit(rabbit_manager, rabbit_config, mock_container): vhost = rabbit_config['vhost'] container = mock_container container.service_name = "service" container.config = rabbit_config ctx_data = {'language': 'en', 'customheader': 'customvalue'} service = Mock() worker_ctx = WorkerContext( container, service, DummyProvider('method'), data=ctx_data ) publisher = Publisher( exchange=foobar_ex, queue=foobar_queue ).bind(container, "publish") publisher.setup() publisher.start() # test queue, exchange and binding created in rabbit exchanges = rabbit_manager.get_exchanges(vhost) queues = rabbit_manager.get_queues(vhost) bindings = rabbit_manager.get_queue_bindings(vhost, foobar_queue.name) assert "foobar_ex" in [exchange['name'] for exchange in exchanges] assert "foobar_queue" in [queue['name'] for queue in queues] assert "foobar_ex" in [binding['source'] for binding in bindings] service.publish = publisher.get_dependency(worker_ctx) service.publish("msg") # test message published to queue messages = rabbit_manager.get_messages(vhost, foobar_queue.name) assert ['"msg"'] == [msg['payload'] for msg in messages] # test message headers assert messages[0]['properties']['headers'] == { 'nameko.language': 'en', 'nameko.customheader': 'customvalue', 'nameko.call_id_stack': ['service.method.0'], }
def test_publish_custom_headers(empty_config, maybe_declare, patch_publisher): container = Mock(spec=ServiceContainer) container.service_name = "srcservice" container.config = empty_config ctx_data = {'language': 'en', 'customheader': 'customvalue'} service = Mock() worker_ctx = CustomWorkerContext(container, service, DummyProvider('method'), data=ctx_data) publisher = Publisher(queue=foobar_queue).bind(container, "publish") producer = Mock() connection = Mock() get_connection, get_producer = patch_publisher(publisher) get_connection.return_value = as_context_manager(connection) get_producer.return_value = as_context_manager(producer) # test declarations publisher.setup() maybe_declare.assert_called_once_with(foobar_queue, connection) # test publish msg = "msg" headers = { 'nameko.language': 'en', 'nameko.customheader': 'customvalue', 'nameko.call_id_stack': ['srcservice.method.0'] } service.publish = publisher.get_dependency(worker_ctx) service.publish(msg, publish_kwarg="value") producer.publish.assert_called_once_with(msg, headers=headers, exchange=foobar_ex, retry=True, retry_policy=DEFAULT_RETRY_POLICY, publish_kwarg="value")
def test_publish_to_rabbit(rabbit_manager, rabbit_config): vhost = rabbit_config["vhost"] container = Mock(spec=ServiceContainer) container.service_name = "service" container.config = rabbit_config container.spawn_managed_thread = eventlet.spawn ctx_data = {"language": "en", "customheader": "customvalue"} service = Mock() worker_ctx = CustomWorkerContext(container, service, DummyProvider("method"), data=ctx_data) publisher = Publisher(exchange=foobar_ex, queue=foobar_queue).bind(container, "publish") # test queue, exchange and binding created in rabbit publisher.setup() publisher.start() exchanges = rabbit_manager.get_exchanges(vhost) queues = rabbit_manager.get_queues(vhost) bindings = rabbit_manager.get_queue_bindings(vhost, foobar_queue.name) assert "foobar_ex" in [exchange["name"] for exchange in exchanges] assert "foobar_queue" in [queue["name"] for queue in queues] assert "foobar_ex" in [binding["source"] for binding in bindings] # test message published to queue service.publish = publisher.get_dependency(worker_ctx) service.publish("msg") messages = rabbit_manager.get_messages(vhost, foobar_queue.name) assert ["msg"] == [msg["payload"] for msg in messages] # test message headers assert messages[0]["properties"]["headers"] == { "nameko.language": "en", "nameko.customheader": "customvalue", "nameko.call_id_stack": ["service.method.0"], }
def test_publish_custom_headers(mock_container, maybe_declare, patch_publisher): container = mock_container container.service_name = "srcservice" ctx_data = {'language': 'en', 'customheader': 'customvalue'} service = Mock() worker_ctx = WorkerContext( container, service, DummyProvider('method'), data=ctx_data ) publisher = Publisher(queue=foobar_queue).bind(container, "publish") producer = Mock() connection = Mock() get_connection, get_producer = patch_publisher(publisher) get_connection.return_value = as_context_manager(connection) get_producer.return_value = as_context_manager(producer) # test declarations publisher.setup() maybe_declare.assert_called_once_with(foobar_queue, connection) # test publish msg = "msg" headers = {'nameko.language': 'en', 'nameko.customheader': 'customvalue', 'nameko.call_id_stack': ['srcservice.method.0']} service.publish = publisher.get_dependency(worker_ctx) service.publish(msg, publish_kwarg="value") producer.publish.assert_called_once_with( msg, headers=headers, exchange=foobar_ex, retry=True, serializer=container.serializer, retry_policy=DEFAULT_RETRY_POLICY, publish_kwarg="value")