def test_should_log_successfully_an_error_raised_by_a_meiga_handler(given_any_petisco): logger = FakeLogger() class UserNotFoundError(Error): pass @use_case_handler(logger=logger) class MyUseCase(UseCase): def execute(self): Failure(UserNotFoundError()).unwrap_or_return() return isSuccess result = MyUseCase().execute() assert_failure(result, value_is_instance_of=UserNotFoundError) first_logging_message = logger.get_logging_messages()[0] second_logging_message = logger.get_logging_messages()[1] assert first_logging_message == ( DEBUG, LogMessageMother.get_use_case( operation="MyUseCase", message="Running Use Case" ).to_dict(), ) assert second_logging_message == ( ERROR, LogMessageMother.get_use_case( operation="MyUseCase", message="Result[status: failure | value: UserNotFoundError] ", ).to_dict(), )
def test_should_log_successfully_an_error_returned_on_a_use_case(given_any_petisco): logger = FakeLogger() @use_case_handler(logger=logger) class MyUseCase(UseCase): def execute(self): return isFailure result = MyUseCase().execute() assert_failure(result, value_is_instance_of=Error) first_logging_message = logger.get_logging_messages()[0] second_logging_message = logger.get_logging_messages()[1] assert first_logging_message == ( DEBUG, LogMessageMother.get_use_case( operation="MyUseCase", message="Running Use Case" ).to_dict(), ) assert second_logging_message == ( ERROR, LogMessageMother.get_use_case( operation="MyUseCase", message="Result[status: failure | value: Error] " ).to_dict(), )
def test_should_use_case_handler_return_a_failure_with_unknown_error_when_raise_an_uncontrolled_exception( given_any_petisco ): logger = FakeLogger() expected_raised_exception = RuntimeError("uncontrolled exception") @use_case_handler(logger=logger) class MyUseCase(UseCase): def execute(self): raise expected_raised_exception result = MyUseCase().execute() assert_failure( result, value_is_instance_of=UnknownError, value_is_equal_to=UnknownError(expected_raised_exception), ) first_logging_message = logger.get_logging_messages()[0] second_logging_message = logger.get_logging_messages()[1] assert first_logging_message == ( DEBUG, LogMessageMother.get_use_case( operation="MyUseCase", message="Running Use Case" ).to_dict(), ) assert ( "value: UnknownError (MyUseCase (Use Case)): RuntimeError: uncontrolled exception.\nTraceback (most recent call last):\n File" in second_logging_message[1]["data"]["message"] )
def test_should_subscriber_handler_always_simulate_a_nack( given_any_petisco, make_user_created_event, given_any_publisher_and_subscriber ): logger = FakeLogger() event = make_user_created_event() tracked_events_spy = TrackedEventsSpy() @subscriber_handler(logger=logger, percentage_simulate_nack=1.0) def main_handler(event: Event): tracked_events_spy.append(event) return isSuccess publisher, subscriber = given_any_publisher_and_subscriber(main_handler) subscriber.start() await_for_subscriber() publisher.publish(event) await_for_events() tracked_events_spy.assert_number_events(0) second_logging_message = logger.get_logging_messages()[1] assert second_logging_message == ( WARNING, LogMessageMother.get_subscriber( operation="main_handler", message="Message rejected (Simulation rejecting 100.0% of the messages)", ).to_dict(), ) subscriber.stop()
def test_should_log_successfully_a_non_error_use_case_without_input_parameters_and_returning_a_string_result( given_any_petisco ): logger = FakeLogger() @use_case_handler(logger=logger) class MyUseCase(UseCase): def execute(self): return Success("Hello Petisco") MyUseCase().execute() first_logging_message = logger.get_logging_messages()[0] second_logging_message = logger.get_logging_messages()[1] assert first_logging_message == ( DEBUG, LogMessageMother.get_use_case( operation="MyUseCase", message="Running Use Case" ).to_dict(), ) assert second_logging_message == ( DEBUG, LogMessageMother.get_use_case( operation="MyUseCase", message="Hello Petisco" ).to_dict(), )
def test_should_log_successfully_a_non_error_use_case_with_input_parameters_but_not_in_the_whitelist( given_any_petisco ): logger = FakeLogger() @use_case_handler(logger=logger) class MyUseCase(UseCase): def execute(self, client_id: str, user_id: str): return Success("Hello Petisco") MyUseCase().execute(client_id="client_id", user_id="user_id") first_logging_message = logger.get_logging_messages()[0] second_logging_message = logger.get_logging_messages()[1] assert first_logging_message == ( DEBUG, LogMessageMother.get_use_case( operation="MyUseCase", message="Running Use Case" ).to_dict(), ) assert second_logging_message == ( DEBUG, LogMessageMother.get_use_case( operation="MyUseCase", message="Hello Petisco" ).to_dict(), )
def test_should_subscriber_handler_return_a_failure_with_unknown_error_when_raise_an_uncontrolled_exception( given_any_petisco, make_user_created_event, given_any_publisher_and_subscriber ): event = make_user_created_event() expected_organization = "acmeorganization" logger = FakeLogger() @subscriber_handler(logger=logger) def main_handler(event: Event, routing_key: RoutingKey): raise RuntimeError("uncontrolled exception") publisher, subscriber = given_any_publisher_and_subscriber( main_handler, organization=expected_organization ) subscriber.start() await_for_subscriber() publisher.publish(event) await_for_events() subscriber.stop() second_logging_message = logger.get_logging_messages()[1] assert second_logging_message[0] == ERROR assert ( "Result[status: failure | value: UnknownError (main_handler (Subscriber)): RuntimeError: uncontrolled exception." in second_logging_message[1]["data"]["message"] ) assert "Input Parameters:" in second_logging_message[1]["data"]["message"]
def test_should_log_successfully_a_filtered_object_by_blacklist_with_a_tuple( given_any_petisco ): logger = FakeLogger() @use_case_handler(logger=logger, logging_types_blacklist=[tuple]) class MyUseCase(UseCase): def execute(self): binary_info = ("my_data", b"This are bytes") return Success(binary_info) result = MyUseCase().execute() assert_success(result) first_logging_message = logger.get_logging_messages()[0] second_logging_message = logger.get_logging_messages()[1] assert first_logging_message == ( DEBUG, LogMessageMother.get_use_case( operation="MyUseCase", message="Running Use Case" ).to_dict(), ) assert second_logging_message == ( DEBUG, LogMessageMother.get_use_case( operation="MyUseCase", message="Success result of type: tuple" ).to_dict(), )
def test_should_subscriber_handler_always_returns_nack_filtering_by_invalid_routing_key( given_any_petisco, make_user_created_event, given_any_publisher_and_subscriber ): logger = FakeLogger() event = make_user_created_event() tracked_events_spy = TrackedEventsSpy() invalid_routing_key = "invalid.routing.key" @subscriber_handler(logger=logger, filter_routing_key=invalid_routing_key) def main_handler(event: Event): tracked_events_spy.append(event) return isSuccess publisher, subscriber = given_any_publisher_and_subscriber(main_handler) subscriber.start() await_for_subscriber() publisher.publish(event) await_for_events() tracked_events_spy.assert_number_events(0) second_logging_message = logger.get_logging_messages()[1] assert second_logging_message == ( WARNING, LogMessageMother.get_subscriber( operation="main_handler", message=f"Message rejected (filtering by routing_key {invalid_routing_key})", ).to_dict(), ) subscriber.stop()
def test_should_execute_successfully_a_empty_controller_with_jwt_requirement_with_user( given_any_petisco, given_any_token_type_with_user, given_headers_provider, given_auth_token_headers_creator, given_any_client_id, given_any_user_id, given_any_correlation_id, given_info_id_only_correlation_id, ): logger = FakeLogger() expected_info_id = InfoId( client_id=given_any_client_id, user_id=given_any_user_id, correlation_id=given_any_correlation_id, ) @controller_handler( logger=logger, token_manager=TokenManager(accepted_tokens=[ AcceptedToken(token_type=given_any_token_type_with_user, require_user=True) ]), headers_provider=given_headers_provider({ **given_auth_token_headers_creator( given_any_token_type_with_user, given_any_client_id, given_any_user_id, ), **given_info_id_only_correlation_id.get_http_headers(), }), ) def my_controller(info_id: InfoId): assert info_id == expected_info_id return Success("Hello Petisco") http_response = my_controller() assert http_response == ({"message": "OK"}, 200) first_logging_message = logger.get_logging_messages()[0] second_logging_message = logger.get_logging_messages()[1] assert first_logging_message == ( DEBUG, LogMessageMother.get_controller( operation="my_controller", message="Processing Request", info_id=expected_info_id, ).to_dict(), ) assert second_logging_message == ( DEBUG, LogMessageMother.get_controller( operation="my_controller", message="Result[status: success | value: Hello Petisco]", info_id=expected_info_id, ).to_dict(), )
def test_should_execute_successfully_a_empty_controller_without_input_parameters( given_any_petisco, given_any_info_id, given_headers_provider): logger = FakeLogger() mock_event_bus = Mock(IEventBus) @controller_handler( app_name="petisco", app_version=__version__, logger=logger, send_request_responded_event=True, event_bus=mock_event_bus, headers_provider=given_headers_provider( given_any_info_id.get_http_headers()), ) def my_controller(): return Success("Hello Petisco") http_response = my_controller() assert http_response == ({"message": "OK"}, 200) first_logging_message = logger.get_logging_messages()[0] second_logging_message = logger.get_logging_messages()[1] assert first_logging_message == ( DEBUG, LogMessageMother.get_controller( operation="my_controller", message="Processing Request", info_id=given_any_info_id, ).to_dict(), ) assert second_logging_message == ( DEBUG, LogMessageMother.get_controller( operation="my_controller", message="Result[status: success | value: Hello Petisco]", info_id=given_any_info_id, ).to_dict(), ) request_responded = mock_event_bus.publish.call_args[0][0] assert isinstance(request_responded, RequestResponded) assert request_responded.app_name == "petisco" assert request_responded.app_version == __version__ assert request_responded.controller == "my_controller" assert request_responded.is_success is True assert request_responded.http_response["content"] == { "message": '{"message": "OK"}', "message_size": 17, } assert request_responded.http_response["status_code"] == 200
def test_should_publish_consume_with_event_handler_notify_when_fail_consumer_with_critical_error( given_any_petisco ): spy = SpyEvents() logger = FakeLogger() notifier = FakeNotifier() class MyCriticalError(CriticalError): pass @event_handler(logger=logger, notifier=notifier) def assert_consumer(event: Event) -> Result[bool, Error]: spy.append(event) return Failure(MyCriticalError(Exception())) event = EventUserCreatedMother.random() subscribers = [ EventSubscriber( event_name=event.event_name, event_version=event.event_version, handlers=[assert_consumer], ) ] configurer = RabbitMqEventConfigurerMother.default() configurer.configure_subscribers(subscribers) bus = RabbitMqEventBusMother.default() bus.publish(event) consumer = RabbitMqEventConsumerMother.without_retry() consumer.add_subscribers(subscribers) consumer.start() sleep(1.0) consumer.stop() configurer.clear() spy.assert_number_unique_events(1) spy.assert_first_event(event) spy.assert_count_by_event_id(event.event_id, 1) first_logging_message = logger.get_logging_messages()[0] assert first_logging_message == ( DEBUG, LogMessageMother.get_event_handler( operation="assert_consumer", message={"event": event.event_name, "body": event.to_json()}, ).to_dict(), ) assert notifier.publish_called assert notifier.publish_times_called == 1
def test_should_returns_an_error_when_a_empty_controller_get_a_required_jwt_token_but_missing_user( given_any_petisco, given_any_token_type, given_headers_provider, given_auth_token_headers_creator, given_any_token_type_with_user, given_any_client_id, given_info_id_only_correlation_id, ): logger = FakeLogger() @controller_handler( logger=logger, token_manager=TokenManager(accepted_tokens=[ AcceptedToken(token_type=given_any_token_type, require_user=True) ]), headers_provider=given_headers_provider( { **given_auth_token_headers_creator( given_any_token_type_with_user, given_any_client_id, None), **given_info_id_only_correlation_id.get_http_headers(), }), ) def my_controller(): return Success("Hello Petisco") http_response = my_controller() assert http_response == ( { "error": { "message": "Access token is missing or invalid. This entry point expects a valid TOKEN Token with require_user=True", "type": "InvalidTokenHttpError", } }, 401, ) first_logging_message = logger.get_logging_messages()[0] assert first_logging_message == ( ERROR, LogMessageMother.get_controller( operation="my_controller", message= "Result[status: failure | value: InvalidTokenError: This entry point expects a valid TOKEN Token with require_user=True]", ).to_dict(), )
def test_should_execute_successfully_a_empty_controller_with_several_jwt_requirement( accepted_tokens, token_type, user_id, expected_status_code, given_any_petisco, given_headers_provider, given_auth_token_headers_creator, given_any_client_id, given_any_correlation_id, given_info_id_only_correlation_id, ): logger = FakeLogger() expected_info_id = InfoId( client_id=given_any_client_id, user_id=user_id, correlation_id=given_any_correlation_id, ) @controller_handler( logger=logger, token_manager=TokenManager(accepted_tokens=accepted_tokens), headers_provider=given_headers_provider({ **given_auth_token_headers_creator(token_type, given_any_client_id, user_id), **given_info_id_only_correlation_id.get_http_headers(), }), ) def my_controller(info_id: InfoId): assert info_id == expected_info_id return Success("Hello Petisco") http_response = my_controller() assert http_response[1] == expected_status_code
def test_should_consumer_react_to_chaos_with_nck_simulation_and_check_logger(): spy = SpyEvents() logger = FakeLogger() def assert_consumer(event: Event) -> Result[bool, Error]: spy.append(event) return isSuccess event = EventUserCreatedMother.random() subscribers = [ EventSubscriber( event_name=event.event_name, event_version=event.event_version, handlers=[assert_consumer], ) ] configurer = RabbitMqEventConfigurerMother.with_retry_ttl_10ms() configurer.configure_subscribers(subscribers) bus = RabbitMqEventBusMother.default() bus.publish(event) max_retries_allowed = 5 chaos = RabbitMqEventChaos(percentage_simulate_nack=1.0) consumer = RabbitMqEventConsumerMother.with_chaos( chaos, max_retries_allowed, logger ) consumer.add_subscribers(subscribers) consumer.start() sleep(1.0) consumer.stop() configurer.clear() assert len(logger.get_logging_messages()) >= 200 first_logging_message = logger.get_logging_messages()[0] assert first_logging_message[0] == DEBUG assert first_logging_message[1]["meta"] == { "layer": "rabbitmq_event_consumer", "operation": "assert_consumer", } assert ( first_logging_message[1]["data"]["message"]["chaos_action"] == "nack simulated" )
def test_should_publish_consume_with_event_handler_when_fail_consumer(): spy = SpyEvents() logger = FakeLogger() @event_handler(logger=logger) def assert_consumer(event: Event) -> Result[bool, Error]: spy.append(event) return isFailure event = EventUserCreatedMother.random() subscribers = [ EventSubscriber( event_name=event.event_name, event_version=event.event_version, handlers=[assert_consumer], ) ] configurer = RabbitMqEventConfigurerMother.default() configurer.configure_subscribers(subscribers) bus = RabbitMqEventBusMother.default() bus.publish(event) consumer = RabbitMqEventConsumerMother.with_max_retries(1) consumer.add_subscribers(subscribers) consumer.start() sleep(1.0) consumer.stop() configurer.clear() spy.assert_number_unique_events(1) spy.assert_first_event(event) spy.assert_count_by_event_id(event.event_id, 1) first_logging_message = logger.get_logging_messages()[0] assert first_logging_message == ( DEBUG, LogMessageMother.get_event_handler( operation="assert_consumer", message={"event": event.event_name, "body": event.to_json()}, ).to_dict(), )
def test_should_consumer_react_to_chaos_with_zero_probability(): spy = SpyEvents() logger = FakeLogger() def assert_consumer(event: Event) -> Result[bool, Error]: spy.append(event) return isSuccess event = EventUserCreatedMother.random() subscribers = [ EventSubscriber( event_name=event.event_name, event_version=event.event_version, handlers=[assert_consumer], ) ] configurer = RabbitMqEventConfigurerMother.with_retry_ttl_10ms() configurer.configure_subscribers(subscribers) bus = RabbitMqEventBusMother.default() bus.publish(event) max_retries_allowed = 5 chaos = RabbitMqEventChaos( percentage_simulate_nack=0.0, percentage_simulate_failures=0.0 ) consumer = RabbitMqEventConsumerMother.with_chaos( chaos, max_retries_allowed, logger ) consumer.add_subscribers(subscribers) consumer.start() sleep(1.0) consumer.stop() configurer.clear() spy.assert_number_unique_events(1) spy.assert_first_event(event) spy.assert_count_by_event_id(event.event_id, 1) assert len(logger.get_logging_messages()) == 2 logging_message = logger.get_logging_messages()[1] assert logging_message[0] == DEBUG assert logging_message[1]["data"]["message"]["derived_action"] == {}
def test_should_execute_with_a_failure_a_empty_controller_without_input_parameters( given_any_petisco, given_any_info_id, given_headers_provider): logger = FakeLogger() @controller_handler( logger=logger, headers_provider=given_headers_provider( given_any_info_id.get_http_headers()), ) def my_controller(headers=None): return isFailure http_response = my_controller() assert http_response == ( { "error": { "message": "Unknown Error", "type": "HttpError" } }, 500, ) first_logging_message = logger.get_logging_messages()[0] second_logging_message = logger.get_logging_messages()[1] assert first_logging_message == ( DEBUG, LogMessageMother.get_controller( operation="my_controller", message="Processing Request", info_id=given_any_info_id, ).to_dict(), ) assert second_logging_message == ( ERROR, LogMessageMother.get_controller( operation="my_controller", message="Result[status: failure | value: Error]", info_id=given_any_info_id, ).to_dict(), )
def test_should_consumer_react_to_chaos_with_failure_simulation_and_check_logger_with_subscribers(): spy = SpyEvents() spy_dead_letter = SpyEvents() logger = FakeLogger() def assert_consumer(event: Event) -> Result[bool, Error]: spy.append(event) return isSuccess def assert_dead_letter_consumer(event: Event) -> Result[bool, Error]: spy_dead_letter.append(event) return isSuccess event = EventUserCreatedMother.random() subscribers = [ EventSubscriber( event_name=event.event_name, event_version=event.event_version, handlers=[assert_consumer], ) ] configurer = RabbitMqEventConfigurerMother.with_main_and_retry_ttl_100ms() configurer.configure_subscribers(subscribers) bus = RabbitMqEventBusMother.default() bus.publish(event) max_retries_allowed = 5 chaos = RabbitMqEventChaos( percentage_simulate_failures=1.0, protected_routing_keys=[ "dead_letter.alice.petisco.1.event.user_created.assert_consumer" ], ) consumer = RabbitMqEventConsumerMother.with_chaos( chaos, max_retries_allowed, logger ) consumer.add_subscribers(subscribers) consumer.add_handler_on_queue( "dead_letter.alice.petisco.1.event.user_created.assert_consumer", assert_dead_letter_consumer, ) consumer.start() sleep(1.5) consumer.stop() configurer.clear() spy.assert_count_by_event_id(event.event_id, 0) spy_dead_letter.assert_count_by_event_id(event.event_id, 1) assert_logger_represents_simulated_failure_scenario(logger, max_retries_allowed)
def test_should_log_an_exception_occurred_on_the_controller( given_any_petisco, given_any_info_id, given_headers_provider): logger = FakeLogger() @controller_handler( logger=logger, headers_provider=given_headers_provider( given_any_info_id.get_http_headers()), ) def my_controller(headers=None): raise RuntimeError("my_controller exception") http_response = my_controller() assert http_response == ( { "error": { "message": "Internal Error.", "type": "InternalHttpError" } }, 500, ) first_logging_message = logger.get_logging_messages()[0] second_logging_message = logger.get_logging_messages()[1] assert first_logging_message == ( DEBUG, LogMessageMother.get_controller( operation="my_controller", message="Processing Request", info_id=given_any_info_id, ).to_dict(), ) assert second_logging_message[0] == ERROR assert "line" in second_logging_message[1]["data"]["message"] assert "RuntimeError" in second_logging_message[1]["data"]["message"] assert "my_controller exception" in second_logging_message[1]["data"][ "message"]
def test_should_use_case_handler_return_a_failure_with_unknown_error_when_raise_an_uncontrolled_exception_with_non_defined_input_parameters( given_any_petisco ): logger = FakeLogger() expected_raised_exception = RuntimeError("uncontrolled exception") input_text = "my-text" input_verbose = True @use_case_handler(logger=logger) class MyUseCase(UseCase): def execute(self, text: str, verbose: bool): raise expected_raised_exception result = MyUseCase().execute(input_text, input_verbose) assert_failure( result, value_is_instance_of=UnknownError, value_is_equal_to=UnknownError(expected_raised_exception), ) assert {"param_1": "my-text", "param_2": True} == result.value.input_parameters first_logging_message = logger.get_logging_messages()[0] second_logging_message = logger.get_logging_messages()[1] assert first_logging_message == ( DEBUG, LogMessageMother.get_use_case( operation="MyUseCase", message="Running Use Case" ).to_dict(), ) assert ( "value: UnknownError (MyUseCase (Use Case)): RuntimeError: uncontrolled exception.\nTraceback (most recent call last):\n File" in second_logging_message[1]["data"]["message"] )
def test_should_execute_successfully_a_filtered_object_by_blacklist( given_any_petisco, given_any_info_id, given_headers_provider): logger = FakeLogger() @controller_handler( logger=logger, headers_provider=given_headers_provider( given_any_info_id.get_http_headers()), ) def my_controller(headers=None): return Success(b"This are bytes") http_response = my_controller() assert http_response == ({"message": "OK"}, 200) first_logging_message = logger.get_logging_messages()[0] second_logging_message = logger.get_logging_messages()[1] assert first_logging_message == ( DEBUG, LogMessageMother.get_controller( operation="my_controller", message="Processing Request", info_id=given_any_info_id, ).to_dict(), ) assert second_logging_message == ( DEBUG, LogMessageMother.get_controller( operation="my_controller", message="Success result of type: bytes", info_id=given_any_info_id, ).to_dict(), )
def test_should_execute_successfully_a_empty_controller_with_correlation_id_as_only_input_parameter( given_any_petisco, given_any_info_id, given_headers_provider): logger = FakeLogger() @controller_handler( logger=logger, headers_provider=given_headers_provider( given_any_info_id.get_http_headers()), ) def my_controller(headers=None): return Success("Hello Petisco") http_response = my_controller() assert http_response == ({"message": "OK"}, 200) first_logging_message = logger.get_logging_messages()[0] second_logging_message = logger.get_logging_messages()[1] assert first_logging_message == ( DEBUG, LogMessageMother.get_controller( operation="my_controller", message="Processing Request", info_id=given_any_info_id, ).to_dict(), ) assert second_logging_message == ( DEBUG, LogMessageMother.get_controller( operation="my_controller", message="Result[status: success | value: Hello Petisco]", info_id=given_any_info_id, ).to_dict(), )
def test_should_log_successfully_a_large_type_with_its_repr(given_any_petisco): logger = FakeLogger() class BinaryInfo(NamedTuple): name: str data: bytes def __repr__(self) -> str: return f"<BinaryInfo {self.name}, len(data)={len(self.data)}>" @use_case_handler(logger=logger) class MyUseCase(UseCase): def execute(self): binary_info = BinaryInfo(name="my_data", data=b"This are bytes") return Success(binary_info) result = MyUseCase().execute() assert_success(result) first_logging_message = logger.get_logging_messages()[0] second_logging_message = logger.get_logging_messages()[1] assert first_logging_message == ( DEBUG, LogMessageMother.get_use_case( operation="MyUseCase", message="Running Use Case" ).to_dict(), ) assert second_logging_message == ( DEBUG, LogMessageMother.get_use_case( operation="MyUseCase", message="<BinaryInfo my_data, len(data)=14>" ).to_dict(), )
def test_should_store_consumer_react_to_chaos_with_nck_simulation_and_send_several_event_to_dead_letter(): spy = SpyEvents() spy_dead_letter_store = SpyEvents() logger = FakeLogger() def assert_consumer(event: Event) -> Result[bool, Error]: spy.append(event) return isSuccess def assert_dead_letter_store_consumer(event: Event) -> Result[bool, Error]: spy_dead_letter_store.append(event) return isSuccess configurer = RabbitMqEventConfigurerMother.with_main_and_retry_ttl_10ms() configurer.configure() bus = RabbitMqEventBusMother.default() event_ids = [] for _ in range(5): event = EventUserCreatedMother.random() event_ids.append(event.event_id) bus.publish(event) max_retries_allowed = 5 chaos = RabbitMqEventChaos(percentage_simulate_nack=1.0) consumer_with_chaos = RabbitMqEventConsumerMother.with_chaos( chaos, max_retries_allowed, logger ) consumer_with_chaos.add_handler_on_store(assert_consumer) consumer_with_chaos.start() sleep(1.0) consumer_with_chaos.stop() consumer_without_chaos = RabbitMqEventConsumerMother.default() consumer_without_chaos.add_handler_on_queue( "dead_letter.store", assert_dead_letter_store_consumer ) consumer_without_chaos.start() sleep(1.0) consumer_without_chaos.stop() configurer.clear() for event_id in event_ids: spy.assert_count_by_event_id(event_id, 0) # Rejected before by Event Chaos spy_dead_letter_store.assert_count_by_event_id(event_id, 1)
def test_should_consumer_react_to_chaos_with_failure_simulation_and_check_logger_without_subscribers(): spy = SpyEvents() spy_dead_letter = SpyEvents() logger = FakeLogger() def assert_store_consumer(event: Event) -> Result[bool, Error]: spy.append(event) return isSuccess def assert_dead_letter_store_consumer(event: Event) -> Result[bool, Error]: spy_dead_letter.append(event) return isSuccess event = EventUserCreatedMother.random() configurer = RabbitMqEventConfigurerMother.with_main_and_retry_ttl_100ms() configurer.configure() bus = RabbitMqEventBusMother.default() bus.publish(event) max_retries_allowed = 5 chaos = RabbitMqEventChaos( percentage_simulate_failures=1.0, protected_routing_keys=["dead_letter.store"] ) consumer = RabbitMqEventConsumerMother.with_chaos( chaos, max_retries_allowed, logger ) consumer.add_handler_on_store(assert_store_consumer) consumer.add_handler_on_queue( "dead_letter.store", assert_dead_letter_store_consumer ) consumer.start() sleep(1.5) consumer.stop() configurer.clear() spy.assert_count_by_event_id(event.event_id, 0) spy_dead_letter.assert_count_by_event_id(event.event_id, 1)
def test_should_publish_event_on_consumer_with_event_handler(): spy = SpyEvents() @event_handler(logger=FakeLogger()) def assert_consumer(event: Event, event_bus: IEventBus) -> BoolResult: spy.append(event) event = EventUserUpdatedMother.random() event_bus.publish(event) return isSuccess event = EventUserCreatedMother.random() subscribers = [ EventSubscriber( event_name=event.event_name, event_version=event.event_version, handlers=[assert_consumer], ) ] configurer = RabbitMqEventConfigurerMother.with_retry_ttl_10ms() configurer.configure_subscribers(subscribers) consumer = RabbitMqEventConsumerMother.with_max_retries(1) consumer.add_subscribers(subscribers) consumer.start() bus = RabbitMqEventBusMother.default() for _ in range(1): event = EventUserCreatedMother.random() bus.publish(event) sleep(1.0) consumer.stop() configurer.clear() spy.assert_number_unique_events(1)