From 711f0df73c4429271a86d79c4fc4538905def18a Mon Sep 17 00:00:00 2001 From: Subhash Bhushan Date: Fri, 12 Jul 2024 21:53:24 -0700 Subject: [PATCH] Move command and event handler setup to `Domain.init()` Factory methods in command handler and event handler were parsing the methods marked with `handle()` and setting up command and event structure for later processing. This has now been moved to `Domain.init()` method because events and commands are not yet ready when command and event handlers are registered. --- src/protean/core/command.py | 7 -- src/protean/core/command_handler.py | 71 ----------- src/protean/core/event.py | 9 +- src/protean/core/event_handler.py | 25 ---- src/protean/domain/__init__.py | 116 ++++++++++++++++++ src/protean/utils/__init__.py | 2 +- .../test_event_association_with_aggregate.py | 2 + .../test_automatic_stream_association.py | 111 ----------------- tests/command_handler/test_basics.py | 12 +- ...st_handle_decorator_in_command_handlers.py | 9 +- tests/domain/test_init.py | 30 +++++ tests/event/test_event_metadata.py | 1 + tests/event/test_raising_events.py | 1 + tests/event/tests.py | 9 ++ tests/event_handler/test_any_event_handler.py | 2 + ...test_handle_decorator_in_event_handlers.py | 3 + .../test_retrieving_handlers_by_event.py | 6 +- .../test_uow_around_event_handlers.py | 1 + tests/event_sourced_aggregates/test_apply.py | 6 +- tests/message/test_message_to_object.py | 1 + tests/server/test_any_event_handler.py | 1 + tests/server/test_command_handling.py | 1 + tests/server/test_error_handling.py | 1 + tests/server/test_event_handling.py | 1 + tests/server/test_handling_all_events.py | 1 + ...st_message_filtering_with_origin_stream.py | 1 + .../test_message_handover_to_engine.py | 1 + .../subscription/test_no_message_filtering.py | 1 + .../test_read_position_updates.py | 1 + 29 files changed, 197 insertions(+), 236 deletions(-) delete mode 100644 tests/command/test_automatic_stream_association.py diff --git a/src/protean/core/command.py b/src/protean/core/command.py index 10e26b34..ee0a77d9 100644 --- a/src/protean/core/command.py +++ b/src/protean/core/command.py @@ -141,11 +141,4 @@ def command_factory(element_cls, domain, **opts): } ) - # Set the command type for the command class - setattr( - element_cls, - "__type__", - f"{domain.name}.{element_cls.__name__}.{element_cls.__version__}", - ) - return element_cls diff --git a/src/protean/core/command_handler.py b/src/protean/core/command_handler.py index 2d024bd9..460f24d3 100644 --- a/src/protean/core/command_handler.py +++ b/src/protean/core/command_handler.py @@ -1,7 +1,4 @@ -import inspect - from protean.container import Element, OptionsMixin -from protean.core.command import BaseCommand from protean.exceptions import IncorrectUsageError, NotSupportedError from protean.utils import DomainObjects, derive_element_class from protean.utils.mixins import HandlerMixin @@ -38,72 +35,4 @@ def command_handler_factory(element_cls, domain, **opts): } ) - # Iterate through methods marked as `@handle` and construct a handler map - if not element_cls._handlers: # Protect against re-registration - methods = inspect.getmembers(element_cls, predicate=inspect.isroutine) - for method_name, method in methods: - if not ( - method_name.startswith("__") and method_name.endswith("__") - ) and hasattr(method, "_target_cls"): - # Throw error if target_cls is not a Command - if not inspect.isclass(method._target_cls) or not issubclass( - method._target_cls, BaseCommand - ): - raise IncorrectUsageError( - { - "_command_handler": [ - f"Method `{method_name}` in Command Handler `{element_cls.__name__}` " - "is not associated with a command" - ] - } - ) - - # Throw error if target_cls is not associated with an aggregate - if not method._target_cls.meta_.part_of: - raise IncorrectUsageError( - { - "_command_handler": [ - f"Command `{method._target_cls.__name__}` in Command Handler `{element_cls.__name__}` " - "is not associated with an aggregate" - ] - } - ) - - if method._target_cls.meta_.part_of != element_cls.meta_.part_of: - raise IncorrectUsageError( - { - "_command_handler": [ - f"Command `{method._target_cls.__name__}` in Command Handler `{element_cls.__name__}` " - "is not associated with the same aggregate as the Command Handler" - ] - } - ) - - command_type = ( - method._target_cls.__type__ - if issubclass(method._target_cls, BaseCommand) - else method._target_cls - ) - - # Do not allow multiple handlers per command - if ( - command_type in element_cls._handlers - and len(element_cls._handlers[command_type]) != 0 - ): - raise NotSupportedError( - f"Command {method._target_cls.__name__} cannot be handled by multiple handlers" - ) - - # `_handlers` maps the command to its handler method - element_cls._handlers[command_type].add(method) - - # Associate Command with the handler's stream - # Order of preference: - # 1. Stream name defined in command - # 2. Stream name derived from aggregate associated with command handler - method._target_cls.meta_.stream_name = ( - method._target_cls.meta_.part_of.meta_.stream_name - or element_cls.meta_.part_of.meta_.stream_name - ) - return element_cls diff --git a/src/protean/core/event.py b/src/protean/core/event.py index 947b57d2..7dd775b3 100644 --- a/src/protean/core/event.py +++ b/src/protean/core/event.py @@ -30,7 +30,7 @@ class Metadata(BaseValueObject): type = String() # Fully Qualified Name of the event/command - fqn = String() + fqn = String(sanitize=False) # Kind of the object # Can be one of "EVENT", "COMMAND" @@ -205,11 +205,4 @@ def domain_event_factory(element_cls, domain, **opts): } ) - # Set the event type for the event class - setattr( - element_cls, - "__type__", - f"{domain.name}.{element_cls.__name__}.{element_cls.__version__}", - ) - return element_cls diff --git a/src/protean/core/event_handler.py b/src/protean/core/event_handler.py index c3b3cfbd..645d6632 100644 --- a/src/protean/core/event_handler.py +++ b/src/protean/core/event_handler.py @@ -1,8 +1,6 @@ -import inspect import logging from protean.container import Element, OptionsMixin -from protean.core.event import BaseEvent from protean.exceptions import IncorrectUsageError, NotSupportedError from protean.utils import DomainObjects, derive_element_class from protean.utils.mixins import HandlerMixin @@ -45,27 +43,4 @@ def event_handler_factory(element_cls, domain, **opts): } ) - # Iterate through methods marked as `@handle` and construct a handler map - # - # Also, if `_target_cls` is an event, associate it with the event handler's - # aggregate or stream - methods = inspect.getmembers(element_cls, predicate=inspect.isroutine) - for method_name, method in methods: - if not ( - method_name.startswith("__") and method_name.endswith("__") - ) and hasattr(method, "_target_cls"): - # `_handlers` is a dictionary mapping the event to the handler method. - if method._target_cls == "$any": - # This replaces any existing `$any` handler, by design. An Event Handler - # can have only one `$any` handler method. - element_cls._handlers["$any"] = {method} - else: - # Target could be an event or an event type string - event_type = ( - method._target_cls.__type__ - if issubclass(method._target_cls, BaseEvent) - else method._target_cls - ) - element_cls._handlers[event_type].add(method) - return element_cls diff --git a/src/protean/domain/__init__.py b/src/protean/domain/__init__.py index 7f8644e2..92a214a8 100644 --- a/src/protean/domain/__init__.py +++ b/src/protean/domain/__init__.py @@ -258,6 +258,15 @@ def init(self, traverse=True): # noqa: C901 # Generate Fact Event Classes self._generate_fact_event_classes() + # Generate and set event/command `__type__` value + self._set_event_and_command_type() + + # Parse and setup handler methods in Command Handlers + self._setup_command_handlers() + + # Parse and setup handler methods in Event Handlers + self._setup_event_handlers() + # Run Validations self._validate_domain() @@ -818,6 +827,113 @@ def _set_aggregate_cluster_options(self): element.cls.meta_.aggregate_cluster.meta_.provider, ) + def _set_event_and_command_type(self): + for element_type in [DomainObjects.EVENT, DomainObjects.COMMAND]: + for _, element in self.registry._elements[element_type.value].items(): + setattr( + element.cls, + "__type__", + ( + f"{self.name}." + # f"{element.cls.meta_.aggregate_cluster.__class__.__name__}." + f"{element.cls.__name__}." + f"{element.cls.__version__}" + ), + ) + + def _setup_command_handlers(self): + for element_type in [DomainObjects.COMMAND_HANDLER]: + for _, element in self.registry._elements[element_type.value].items(): + # Iterate through methods marked as `@handle` and construct a handler map + if not element.cls._handlers: # Protect against re-registration + methods = inspect.getmembers( + element.cls, predicate=inspect.isroutine + ) + for method_name, method in methods: + if not ( + method_name.startswith("__") and method_name.endswith("__") + ) and hasattr(method, "_target_cls"): + # Throw error if target_cls is not a Command + if not inspect.isclass( + method._target_cls + ) or not issubclass(method._target_cls, BaseCommand): + raise IncorrectUsageError( + { + "_command_handler": [ + f"Method `{method_name}` in Command Handler `{element.cls.__name__}` " + "is not associated with a command" + ] + } + ) + + # Throw error if target_cls is not associated with an aggregate + if not method._target_cls.meta_.part_of: + raise IncorrectUsageError( + { + "_command_handler": [ + f"Command `{method._target_cls.__name__}` in Command Handler `{element.cls.__name__}` " + "is not associated with an aggregate" + ] + } + ) + + if ( + method._target_cls.meta_.part_of + != element.cls.meta_.part_of + ): + raise IncorrectUsageError( + { + "_command_handler": [ + f"Command `{method._target_cls.__name__}` in Command Handler `{element.cls.__name__}` " + "is not associated with the same aggregate as the Command Handler" + ] + } + ) + + command_type = ( + method._target_cls.__type__ + if issubclass(method._target_cls, BaseCommand) + else method._target_cls + ) + + # Do not allow multiple handlers per command + if ( + command_type in element.cls._handlers + and len(element.cls._handlers[command_type]) != 0 + ): + raise NotSupportedError( + f"Command {method._target_cls.__name__} cannot be handled by multiple handlers" + ) + + # `_handlers` maps the command to its handler method + element.cls._handlers[command_type].add(method) + + def _setup_event_handlers(self): + for element_type in [DomainObjects.EVENT_HANDLER]: + for _, element in self.registry._elements[element_type.value].items(): + # Iterate through methods marked as `@handle` and construct a handler map + # + # Also, if `_target_cls` is an event, associate it with the event handler's + # aggregate or stream + methods = inspect.getmembers(element.cls, predicate=inspect.isroutine) + for method_name, method in methods: + if not ( + method_name.startswith("__") and method_name.endswith("__") + ) and hasattr(method, "_target_cls"): + # `_handlers` is a dictionary mapping the event to the handler method. + if method._target_cls == "$any": + # This replaces any existing `$any` handler, by design. An Event Handler + # can have only one `$any` handler method. + element.cls._handlers["$any"] = {method} + else: + # Target could be an event or an event type string + event_type = ( + method._target_cls.__type__ + if issubclass(method._target_cls, BaseEvent) + else method._target_cls + ) + element.cls._handlers[event_type].add(method) + def _generate_fact_event_classes(self): """Generate FactEvent classes for all aggregates with `fact_events` enabled""" for element_type in [ diff --git a/src/protean/utils/__init__.py b/src/protean/utils/__init__.py index b4b92be0..b2b29712 100644 --- a/src/protean/utils/__init__.py +++ b/src/protean/utils/__init__.py @@ -83,7 +83,7 @@ def import_from_full_path(domain, path): def fully_qualified_name(cls): """Return Fully Qualified name along with module""" - return ".".join([cls.__module__, cls.__name__]) + return ".".join([cls.__module__, cls.__qualname__]) fqn = fully_qualified_name diff --git a/tests/aggregate/events/test_event_association_with_aggregate.py b/tests/aggregate/events/test_event_association_with_aggregate.py index b28db345..6508cadb 100644 --- a/tests/aggregate/events/test_event_association_with_aggregate.py +++ b/tests/aggregate/events/test_event_association_with_aggregate.py @@ -57,6 +57,7 @@ def register_elements(test_domain): test_domain.register(UserRegistered, part_of=User) test_domain.register(UserActivated, part_of=User) test_domain.register(UserRenamed, part_of=User) + test_domain.init(traverse=False) def test_an_unassociated_event_throws_error(test_domain): @@ -72,6 +73,7 @@ def test_an_unassociated_event_throws_error(test_domain): def test_that_event_associated_with_another_aggregate_throws_error(test_domain): test_domain.register(User2) test_domain.register(UserUnknownEvent, part_of=User2) + test_domain.init(traverse=False) user = User.register(user_id="1", name="", email="") with pytest.raises(ConfigurationError) as exc: diff --git a/tests/command/test_automatic_stream_association.py b/tests/command/test_automatic_stream_association.py deleted file mode 100644 index 83bb4183..00000000 --- a/tests/command/test_automatic_stream_association.py +++ /dev/null @@ -1,111 +0,0 @@ -from __future__ import annotations - -import pytest - -from protean import BaseCommand, BaseCommandHandler, BaseEventSourcedAggregate, handle -from protean.fields import DateTime, Identifier, String - - -class User(BaseEventSourcedAggregate): - email = String() - name = String() - password_hash = String() - - -class Email(BaseEventSourcedAggregate): - email = String() - sent_at = DateTime() - - -class Register(BaseCommand): - id = Identifier() - email = String() - name = String() - password_hash = String() - - -class Activate(BaseCommand): - id = Identifier() - activated_at = DateTime() - - -class Login(BaseCommand): - id = Identifier() - activated_at = DateTime() - - -class Subscribe(BaseCommand): - """An event generated by an external system in its own stream, - that is consumed and stored as part of the User aggregate. - """ - - id = Identifier() - - -class Send(BaseCommand): - email = String() - sent_at = DateTime() - - -class Recall(BaseCommand): - email = String() - sent_at = DateTime() - - -class UserCommandHandler(BaseCommandHandler): - @handle(Register) - def send_activation_email(self, _: Register) -> None: - pass - - @handle(Activate) - def provision_user(self, _: Activate) -> None: - pass - - @handle(Login) - def login(self, _: Login) -> None: - pass - - @handle(Subscribe) - def subscribe_for_notifications(self, _: Subscribe) -> None: - pass - - -class EmailCommandHandler(BaseCommandHandler): - @handle(Send) - def send_mail(self, _: Send) -> None: - pass - - @handle(Recall) - def recall(self, _: Recall) -> None: - pass - - -@pytest.fixture(autouse=True) -def register(test_domain): - test_domain.register(User) - test_domain.register(Login, part_of=User) - test_domain.register(Register, part_of=User) - test_domain.register(Activate, part_of=User) - test_domain.register(Subscribe, part_of=User) - test_domain.register(Email) - test_domain.register(Send, part_of=Email) - test_domain.register(Recall, part_of=Email) - test_domain.register(UserCommandHandler, part_of=User) - test_domain.register(EmailCommandHandler, part_of=Email) - - -def test_automatic_association_of_events_with_aggregate_and_stream(): - assert Register.meta_.part_of is User - assert Register.meta_.stream_name == "user" - - assert Activate.meta_.part_of is User - assert Activate.meta_.stream_name == "user" - - assert Subscribe.meta_.part_of is User - assert Subscribe.meta_.stream_name == "user" - - assert Send.meta_.part_of is Email - assert Send.meta_.stream_name == "email" - - assert Recall.meta_.part_of is Email - assert Recall.meta_.stream_name == "email" diff --git a/tests/command_handler/test_basics.py b/tests/command_handler/test_basics.py index 73eeb4c1..e1fea527 100644 --- a/tests/command_handler/test_basics.py +++ b/tests/command_handler/test_basics.py @@ -34,8 +34,10 @@ def something(self, _: Registered): pass test_domain.register(User) + test_domain.register(UserCommandHandlers, part_of=User) + with pytest.raises(IncorrectUsageError) as exc: - test_domain.register(UserCommandHandlers, part_of=User) + test_domain.init(traverse=False) assert exc.value.messages == { "_command_handler": [ @@ -51,8 +53,10 @@ def something(self, _: Register): pass test_domain.register(User) + test_domain.register(UserCommandHandlers, part_of=User) + with pytest.raises(IncorrectUsageError) as exc: - test_domain.register(UserCommandHandlers, part_of=User) + test_domain.init(traverse=False) assert exc.value.messages == { "_command_handler": [ @@ -76,8 +80,10 @@ class User2(BaseAggregate): test_domain.register(User) test_domain.register(User2) test_domain.register(Register, part_of=User) + test_domain.register(UserCommandHandlers, part_of=User2) + with pytest.raises(IncorrectUsageError) as exc: - test_domain.register(UserCommandHandlers, part_of=User2) + test_domain.init(traverse=False) assert exc.value.messages == { "_command_handler": [ diff --git a/tests/command_handler/test_handle_decorator_in_command_handlers.py b/tests/command_handler/test_handle_decorator_in_command_handlers.py index 26a97e66..fa7461e0 100644 --- a/tests/command_handler/test_handle_decorator_in_command_handlers.py +++ b/tests/command_handler/test_handle_decorator_in_command_handlers.py @@ -30,6 +30,7 @@ def register(self, command: Register) -> None: test_domain.register(User) test_domain.register(Register, part_of=User) test_domain.register(UserCommandHandlers, part_of=User) + test_domain.init(traverse=False) assert Register.__type__ in UserCommandHandlers._handlers @@ -83,10 +84,12 @@ def register(self, event: Register) -> None: def provision_user_account(self, event: Register) -> None: pass + test_domain.register(User) + test_domain.register(Register, part_of=User) + test_domain.register(UserCommandHandlers, part_of=User) + with pytest.raises(NotSupportedError) as exc: - test_domain.register(User) - test_domain.register(Register, part_of=User) - test_domain.register(UserCommandHandlers, part_of=User) + test_domain.init(traverse=False) assert ( exc.value.args[0] == "Command Register cannot be handled by multiple handlers" diff --git a/tests/domain/test_init.py b/tests/domain/test_init.py index e63ff12d..669d1ecc 100644 --- a/tests/domain/test_init.py +++ b/tests/domain/test_init.py @@ -31,12 +31,42 @@ def test_domain_init_calls_resolve_references(self, test_domain): test_domain.init(traverse=False) mock_resolve_references.assert_called_once() + def test_domain_init_assigns_aggregate_clusters(self, test_domain): + mock_assign_aggregate_clusters = Mock() + test_domain._assign_aggregate_clusters = mock_assign_aggregate_clusters + test_domain.init(traverse=False) + mock_assign_aggregate_clusters.assert_called_once() + + def test_domain_init_sets_aggregate_cluster_options(self, test_domain): + mock_set_aggregate_cluster_options = Mock() + test_domain._set_aggregate_cluster_options = mock_set_aggregate_cluster_options + test_domain.init(traverse=False) + mock_set_aggregate_cluster_options.assert_called_once() + def test_domain_init_constructs_fact_events(self, test_domain): mock_generate_fact_event_classes = Mock() test_domain._generate_fact_event_classes = mock_generate_fact_event_classes test_domain.init(traverse=False) mock_generate_fact_event_classes.assert_called_once() + def test_domain_init_sets_event_command_types(self, test_domain): + mock_set_event_and_command_type = Mock() + test_domain._set_event_and_command_type = mock_set_event_and_command_type + test_domain.init(traverse=False) + mock_set_event_and_command_type.assert_called_once() + + def test_domain_init_sets_up_command_handlers(self, test_domain): + mock_setup_command_handlers = Mock() + test_domain._setup_command_handlers = mock_setup_command_handlers + test_domain.init(traverse=False) + mock_setup_command_handlers.assert_called_once() + + def test_domain_init_sets_up_event_handlers(self, test_domain): + mock_setup_event_handlers = Mock() + test_domain._setup_event_handlers = mock_setup_event_handlers + test_domain.init(traverse=False) + mock_setup_event_handlers.assert_called_once() + class TestDomainInitializationCalls: @patch.object(Providers, "_initialize") diff --git a/tests/event/test_event_metadata.py b/tests/event/test_event_metadata.py index b6f9c5ce..36975a57 100644 --- a/tests/event/test_event_metadata.py +++ b/tests/event/test_event_metadata.py @@ -80,6 +80,7 @@ class UserLoggedIn(BaseEvent): user_id = Identifier(identifier=True) test_domain.register(UserLoggedIn, part_of=User) + test_domain.init(traverse=False) event = UserLoggedIn(user_id=str(uuid4())) assert event._metadata.version == "v2" diff --git a/tests/event/test_raising_events.py b/tests/event/test_raising_events.py index b524c56e..2ae10c0d 100644 --- a/tests/event/test_raising_events.py +++ b/tests/event/test_raising_events.py @@ -21,6 +21,7 @@ class UserLoggedIn(BaseEvent): def test_raising_event(test_domain): test_domain.register(User, stream_name="authentication") test_domain.register(UserLoggedIn, part_of=User) + test_domain.init(traverse=False) identifier = str(uuid4()) user = User(id=identifier, email="test@example.com", name="Test User") diff --git a/tests/event/tests.py b/tests/event/tests.py index 759c2271..335e8c9a 100644 --- a/tests/event/tests.py +++ b/tests/event/tests.py @@ -40,6 +40,7 @@ class UserAdded(BaseEvent): name = String(max_length=50) test_domain.register(UserAdded, part_of=User) + test_domain.init(traverse=False) user = User( id=str(uuid.uuid4()), @@ -91,6 +92,7 @@ class UserAdded(BaseEvent): test_domain.register(User) test_domain.register(UserAdded, part_of=User) + test_domain.init(traverse=False) assert UserAdded( { @@ -110,6 +112,7 @@ def test_that_base_domain_event_class_cannot_be_instantiated(self): def test_that_domain_event_can_be_instantiated(self, test_domain): test_domain.register(Person) test_domain.register(PersonAdded, part_of=Person) + test_domain.init(traverse=False) service = PersonAdded(id=uuid.uuid4(), first_name="John", last_name="Doe") assert service is not None @@ -131,6 +134,12 @@ def special_method(self): class TestDomainEventEquivalence: + @pytest.fixture(autouse=True) + def register_elements(self, test_domain): + test_domain.register(Person) + test_domain.register(PersonAdded, part_of=Person) + test_domain.init(traverse=False) + def test_that_two_domain_events_with_same_values_are_considered_equal(self): identifier = uuid.uuid4() event_1 = PersonAdded(id=identifier, first_name="John", last_name="Doe") diff --git a/tests/event_handler/test_any_event_handler.py b/tests/event_handler/test_any_event_handler.py index 2031824a..e0f9d0c6 100644 --- a/tests/event_handler/test_any_event_handler.py +++ b/tests/event_handler/test_any_event_handler.py @@ -19,6 +19,7 @@ def handler2(self, event: BaseEvent) -> None: def test_any_handler(test_domain): test_domain.register(AllEventHandler, stream_name="$all") + test_domain.init(traverse=False) len(AllEventHandler._handlers) == 1 assert AllEventHandler._handlers["$any"] == {AllEventHandler.universal_handler} @@ -26,6 +27,7 @@ def test_any_handler(test_domain): def test_that_there_can_be_only_one_any_handler_method_per_event_handler(test_domain): test_domain.register(MultipleAnyEventHandler, stream_name="$all") + test_domain.init(traverse=False) assert len(MultipleAnyEventHandler._handlers["$any"]) == 1 assert MultipleAnyEventHandler._handlers["$any"] == { diff --git a/tests/event_handler/test_handle_decorator_in_event_handlers.py b/tests/event_handler/test_handle_decorator_in_event_handlers.py index 068726af..ea9e3a76 100644 --- a/tests/event_handler/test_handle_decorator_in_event_handlers.py +++ b/tests/event_handler/test_handle_decorator_in_event_handlers.py @@ -28,6 +28,7 @@ def send_email_notification(self, event: Registered) -> None: test_domain.register(User) test_domain.register(Registered, part_of=User) test_domain.register(UserEventHandlers, part_of=User) + test_domain.init(traverse=False) assert Registered.__type__ in UserEventHandlers._handlers @@ -46,6 +47,7 @@ def updated_billing_address(self, event: AddressChanged) -> None: test_domain.register(Registered, part_of=User) test_domain.register(AddressChanged, part_of=User) test_domain.register(UserEventHandlers, part_of=User) + test_domain.init(traverse=False) assert len(UserEventHandlers._handlers) == 2 assert all( @@ -80,6 +82,7 @@ def provision_user_accounts(self, event: Registered) -> None: test_domain.register(User) test_domain.register(UserEventHandlers, part_of=User) + test_domain.init(traverse=False) assert len(UserEventHandlers._handlers) == 1 # Against Registered Event diff --git a/tests/event_handler/test_retrieving_handlers_by_event.py b/tests/event_handler/test_retrieving_handlers_by_event.py index df33f74c..bfee2ac0 100644 --- a/tests/event_handler/test_retrieving_handlers_by_event.py +++ b/tests/event_handler/test_retrieving_handlers_by_event.py @@ -85,20 +85,20 @@ def register_elements(test_domain): def test_retrieving_handler_by_event(test_domain): - test_domain._initialize() + test_domain.init(traverse=False) assert test_domain.handlers_for(Registered()) == {UserEventHandler, UserMetrics} assert test_domain.handlers_for(Sent()) == {EmailEventHandler} def test_that_all_streams_handler_is_returned(test_domain): test_domain.register(AllEventsHandler, stream_name="$all") - test_domain._initialize() + test_domain.init(traverse=False) assert test_domain.handlers_for(Renamed()) == {AllEventsHandler} def test_that_all_streams_handler_is_always_returned_with_other_handlers(test_domain): test_domain.register(AllEventsHandler, stream_name="$all") - test_domain._initialize() + test_domain.init(traverse=False) assert test_domain.handlers_for(Registered()) == { UserEventHandler, diff --git a/tests/event_handler/test_uow_around_event_handlers.py b/tests/event_handler/test_uow_around_event_handlers.py index 44e25428..755befbc 100644 --- a/tests/event_handler/test_uow_around_event_handlers.py +++ b/tests/event_handler/test_uow_around_event_handlers.py @@ -30,6 +30,7 @@ def send_email_notification(self, event: Registered) -> None: def test_that_method_is_enclosed_in_uow(mock_exit, mock_dummy, mock_enter, test_domain): test_domain.register(User) test_domain.register(Registered, part_of=User) + test_domain.init(traverse=False) mock_parent = mock.Mock() diff --git a/tests/event_sourced_aggregates/test_apply.py b/tests/event_sourced_aggregates/test_apply.py index ae6cc058..26a98b27 100644 --- a/tests/event_sourced_aggregates/test_apply.py +++ b/tests/event_sourced_aggregates/test_apply.py @@ -159,13 +159,11 @@ class UserArchived(BaseEvent): user_id = Identifier(required=True) test_domain.register(UserArchived, part_of=User) + test_domain.init(traverse=False) user = User(user_id=str(uuid4()), name="", email="") with pytest.raises(NotImplementedError) as exc: user._apply(UserArchived(user_id=user.user_id)) - assert ( - exc.value.args[0] - == "No handler registered for event `tests.event_sourced_aggregates.test_apply.UserArchived` in `User`" - ) + assert exc.value.args[0].startswith("No handler registered for event") diff --git a/tests/message/test_message_to_object.py b/tests/message/test_message_to_object.py index ae0eb16d..df8dab64 100644 --- a/tests/message/test_message_to_object.py +++ b/tests/message/test_message_to_object.py @@ -49,6 +49,7 @@ def register(test_domain): test_domain.register(Registered, part_of=User) test_domain.register(SendEmail) test_domain.register(SendEmailCommand, part_of=SendEmail) + test_domain.init(traverse=False) def test_construct_event_from_message(): diff --git a/tests/server/test_any_event_handler.py b/tests/server/test_any_event_handler.py index 36a48b96..8333b223 100644 --- a/tests/server/test_any_event_handler.py +++ b/tests/server/test_any_event_handler.py @@ -39,6 +39,7 @@ async def test_that_an_event_handler_can_be_associated_with_an_all_stream(test_d test_domain.register(User) test_domain.register(Registered, part_of=User) test_domain.register(UserEventHandler, part_of=User) + test_domain.init(traverse=False) identifier = str(uuid4()) user = User( diff --git a/tests/server/test_command_handling.py b/tests/server/test_command_handling.py index df1fba98..94ccc758 100644 --- a/tests/server/test_command_handling.py +++ b/tests/server/test_command_handling.py @@ -46,6 +46,7 @@ async def test_handler_invocation(test_domain): test_domain.register(Register, part_of=User) test_domain.register(Activate, part_of=User) test_domain.register(UserCommandHandler, part_of=User) + test_domain.init(traverse=False) identifier = str(uuid4()) command = Register( diff --git a/tests/server/test_error_handling.py b/tests/server/test_error_handling.py index 8f2fca26..9552968d 100644 --- a/tests/server/test_error_handling.py +++ b/tests/server/test_error_handling.py @@ -51,6 +51,7 @@ async def test_that_exception_is_raised(test_domain): test_domain.register(User) test_domain.register(Registered, part_of=User) test_domain.register(UserEventHandler, part_of=User) + test_domain.init(traverse=False) identifier = str(uuid4()) user = User( diff --git a/tests/server/test_event_handling.py b/tests/server/test_event_handling.py index 53a1c3ec..c42718a2 100644 --- a/tests/server/test_event_handling.py +++ b/tests/server/test_event_handling.py @@ -41,6 +41,7 @@ async def test_handler_invocation(test_domain): test_domain.register(User) test_domain.register(Registered, part_of=User) test_domain.register(UserEventHandler, part_of=User) + test_domain.init(traverse=False) identifier = str(uuid4()) user = User( diff --git a/tests/server/test_handling_all_events.py b/tests/server/test_handling_all_events.py index a66fbaba..87f37bd2 100644 --- a/tests/server/test_handling_all_events.py +++ b/tests/server/test_handling_all_events.py @@ -53,6 +53,7 @@ async def test_that_any_message_can_be_handled_with_any_handler(test_domain): test_domain.register(Post) test_domain.register(Created, part_of=Post) test_domain.register(SystemMetrics, stream_name="$all") + test_domain.init(traverse=False) identifier = str(uuid4()) user = User( diff --git a/tests/subscription/test_message_filtering_with_origin_stream.py b/tests/subscription/test_message_filtering_with_origin_stream.py index 6e67f55d..9c4da356 100644 --- a/tests/subscription/test_message_filtering_with_origin_stream.py +++ b/tests/subscription/test_message_filtering_with_origin_stream.py @@ -76,6 +76,7 @@ def register_elements(test_domain): test_domain.register(Email) test_domain.register(Sent, part_of=Email) test_domain.register(EmailEventHandler, stream_name="email", source_stream="user") + test_domain.init(traverse=False) @pytest.mark.asyncio diff --git a/tests/subscription/test_message_handover_to_engine.py b/tests/subscription/test_message_handover_to_engine.py index 0672512f..062fa384 100644 --- a/tests/subscription/test_message_handover_to_engine.py +++ b/tests/subscription/test_message_handover_to_engine.py @@ -57,6 +57,7 @@ async def test_that_subscription_invokes_engine_handler_on_message( test_domain.register(User) test_domain.register(Registered, part_of=User) test_domain.register(UserEventHandler, part_of=User) + test_domain.init(traverse=False) identifier = str(uuid4()) user = User.register( diff --git a/tests/subscription/test_no_message_filtering.py b/tests/subscription/test_no_message_filtering.py index 7065cef5..e43e19fa 100644 --- a/tests/subscription/test_no_message_filtering.py +++ b/tests/subscription/test_no_message_filtering.py @@ -75,6 +75,7 @@ def register_elements(test_domain): test_domain.register(Email) test_domain.register(Sent, part_of=Email) test_domain.register(EmailEventHandler, stream_name="email") + test_domain.init(traverse=False) @pytest.mark.asyncio diff --git a/tests/subscription/test_read_position_updates.py b/tests/subscription/test_read_position_updates.py index 9179e20e..09f6c692 100644 --- a/tests/subscription/test_read_position_updates.py +++ b/tests/subscription/test_read_position_updates.py @@ -72,6 +72,7 @@ def register_elements(test_domain): test_domain.register(Sent, part_of=Email) test_domain.register(UserEventHandler, part_of=User) test_domain.register(EmailEventHandler, stream_name="email") + test_domain.init(traverse=False) @pytest.mark.asyncio