def test_equality_comparison(self):
     entity_id1 = uuid4()
     event1 = Example.Created(
         originator_id=entity_id1,
         originator_topic=get_topic(Example),
         a=1,
         b=2,
         timestamp=3,
     )
     event2 = Example.Created(
         originator_id=entity_id1,
         originator_topic=get_topic(Example),
         a=1,
         b=2,
         timestamp=3,
     )
     event3 = Example.Created(
         originator_id=entity_id1,
         originator_topic=get_topic(Example),
         a=3,
         b=2,
         timestamp=3,
     )
     self.assertEqual(event1, event2)
     self.assertNotEqual(event1, event3)
     self.assertNotEqual(event2, event3)
     self.assertNotEqual(event2, None)
    def test_event_attributes(self):
        entity_id1 = uuid4()
        event = Example.Created(originator_id=entity_id1,
                                originator_topic=get_topic(Example),
                                a=1,
                                b=2)

        # Check constructor keyword args lead to read-only attributes.
        self.assertEqual(1, event.a)
        self.assertEqual(2, event.b)
        self.assertRaises(AttributeError, getattr, event, "c")
        self.assertRaises(AttributeError, setattr, event, "c", 3)

        # Check domain event has auto-generated timestamp.
        self.assertIsInstance(event.timestamp, Decimal)

        # Check timestamp value can be given to domain events.
        event1 = Example.Created(
            originator_id=entity_id1,
            originator_topic=get_topic(Example),
            a=1,
            b=2,
            timestamp=3,
        )
        self.assertEqual(3, event1.timestamp)
Exemplo n.º 3
0
    def test_all_domain_events(self):
        event_store = self.construct_event_store()

        # Check there are zero domain events in total.
        domain_events = event_store.all_domain_events()
        domain_events = list(domain_events)
        self.assertEqual(len(domain_events), 0)

        # Store a domain event.
        entity_id1 = uuid4()
        event1 = Example.Created(originator_id=entity_id1, a=1, b=2)
        event_store.append(event1)

        # Store another domain event for the same entity.
        event1 = Example.AttributeChanged(originator_id=entity_id1,
                                          a=1,
                                          b=2,
                                          originator_version=1)
        event_store.append(event1)

        # Store a domain event for a different entity.
        entity_id2 = uuid4()
        event1 = Example.Created(originator_id=entity_id2, a=1, b=2)
        event_store.append(event1)

        # Check there are three domain events in total.
        domain_events = event_store.all_domain_events()
        domain_events = list(domain_events)
        self.assertEqual(len(domain_events), 3)
Exemplo n.º 4
0
 def test_equality_comparison(self):
     entity_id1 = uuid4()
     event1 = Example.Created(entity_id=entity_id1, a=1, b=2, timestamp=3)
     event2 = Example.Created(entity_id=entity_id1, a=1, b=2, timestamp=3)
     event3 = Example.Created(entity_id=entity_id1, a=3, b=2, timestamp=3)
     self.assertEqual(event1, event2)
     self.assertNotEqual(event1, event3)
     self.assertNotEqual(event2, event3)
     self.assertNotEqual(event2, None)
Exemplo n.º 5
0
    def test_replay_entity(self):
        # Store example events.

        # Create entity1.
        entity_id1 = uuid4()
        event1 = Example.Created(originator_id=entity_id1, a=1, b=2)
        self.entity_event_store.append(event1)

        # Create entity2.
        entity_id2 = uuid4()
        event2 = Example.Created(originator_id=entity_id2, a=2, b=4)
        self.entity_event_store.append(event2)

        # Create entity3.
        entity_id3 = uuid4()
        event3 = Example.Created(originator_id=entity_id3, a=3, b=6)
        self.entity_event_store.append(event3)

        # Discard entity3.
        event4 = Example.Discarded(originator_id=entity_id3,
                                   originator_version=1)
        self.entity_event_store.append(event4)

        # Check the entities can be replayed.
        event_player = EventPlayer(event_store=self.entity_event_store,
                                   mutator=Example._mutate)

        # Check recovered entities have correct attribute values.
        recovered1 = event_player.replay_entity(entity_id1)
        self.assertEqual(entity_id1, recovered1.id)
        self.assertEqual(1, recovered1.a)

        recovered2 = event_player.replay_entity(entity_id2)
        self.assertEqual(2, recovered2.a)

        recovered3 = event_player.replay_entity(entity_id3)
        self.assertEqual(None, recovered3)

        # Check it works for "short" entities (should be faster, but the main thing is that it still works).
        # - just use a trivial mutate that always instantiates the 'Example'.
        event5 = Example.AttributeChanged(originator_id=entity_id1,
                                          originator_version=1,
                                          name='a',
                                          value=10)
        self.entity_event_store.append(event5)

        recovered1 = event_player.replay_entity(entity_id1)
        self.assertEqual(10, recovered1.a)

        event_player = EventPlayer(
            event_store=self.entity_event_store,
            mutator=Example._mutate,
            is_short=True,
        )
        self.assertEqual(10, event_player.replay_entity(entity_id1).a)
Exemplo n.º 6
0
 def test_hash(self):
     entity_id1 = uuid4()
     event1 = Example.Created(originator_id=entity_id1,
                              a=1,
                              b=2,
                              timestamp=3)
     event2 = Example.Created(originator_id=entity_id1,
                              a=1,
                              b=2,
                              timestamp=3)
     self.assertEqual(hash(event1), hash(event2))
    def test_get_item(self):
        # Setup an event store.
        event_store = self.construct_event_store()

        # Put an event in the event store.
        entity_id = uuid4()
        event_store.store(
            Example.Created(
                a=1,
                b=2,
                originator_id=entity_id,
                originator_topic=get_topic(Example),
            ))

        # Construct a repository.
        event_sourced_repo = EventSourcedRepository(event_store=event_store)

        # Check the entity attributes.
        example = event_sourced_repo[entity_id]
        self.assertEqual(1, example.a)
        self.assertEqual(2, example.b)
        self.assertEqual(entity_id, example.id)

        # Setup an example repository, using the subclass ExampleRepository.
        example_repo = ExampleRepository(event_store=event_store)

        # Check the repo has the example.
        self.assertIn(entity_id, example_repo)
        self.assertNotIn(uuid4(), example_repo)

        # Check the entity attributes.
        example = example_repo[entity_id]
        self.assertEqual(1, example.a)
        self.assertEqual(2, example.b)
        self.assertEqual(entity_id, example.id)
Exemplo n.º 8
0
    def test_event_attributes(self):
        entity_id1 = uuid4()
        event = Example.Created(entity_id=entity_id1, a=1, b=2)

        # Check constructor keyword args lead to read-only attributes.
        self.assertEqual(1, event.a)
        self.assertEqual(2, event.b)
        self.assertRaises(AttributeError, getattr, event, 'c')
        self.assertRaises(AttributeError, setattr, event, 'c', 3)

        # Check domain event has auto-generated timestamp.
        self.assertIsInstance(event.timestamp, float)

        # Check timestamp value can be given to domain events.
        event1 = Example.Created(entity_id=entity_id1, a=1, b=2, timestamp=3)
        self.assertEqual(3, event1.timestamp)
Exemplo n.º 9
0
    def test_get_item(self):
        # Setup an event store.
        event_store = self.construct_event_store()

        # Put an event in the event store.
        entity_id = uuid4()
        event_store.append(Example.Created(entity_id=entity_id, a=1, b=2))

        # Check ValueError is raised if repo doesn't have a mutator function...
        with self.assertRaises(ValueError):
            EventSourcedRepository(event_store=event_store, mutator=None)
        # ...and isn't if we pass a mutator function as a constructor arg.
        event_sourced_repo = EventSourcedRepository(event_store=event_store,
                                                    mutator=Example.mutate)

        # Check the entity attributes.
        example = event_sourced_repo[entity_id]
        self.assertEqual(1, example.a)
        self.assertEqual(2, example.b)
        self.assertEqual(entity_id, example.id)

        # Setup an example repository, using the subclass ExampleRepository.
        example_repo = ExampleRepository(event_store=event_store)

        # Check the repo has the example.
        self.assertIn(entity_id, example_repo)
        self.assertNotIn(uuid4(), example_repo)

        # Check the entity attributes.
        example = example_repo[entity_id]
        self.assertEqual(1, example.a)
        self.assertEqual(2, example.b)
        self.assertEqual(entity_id, example.id)
Exemplo n.º 10
0
 def test_repr(self):
     entity_id1 = uuid4()
     event1 = Example.Created(originator_id=entity_id1,
                              a=1,
                              b=2,
                              timestamp=3)
     self.assertEqual(
         "Example.Created(a=1, b=2, originator_id={}, originator_version=0, timestamp=3)"
         .format(repr(entity_id1)), repr(event1))
Exemplo n.º 11
0
    def test_get_entity(self):
        # Store example events.
        entity_id1 = uuid4()
        event1 = Example.Created(entity_id=entity_id1, a=1, b=2)
        self.version_entity_event_store.append(event1)
        entity_id2 = uuid4()
        event2 = Example.Created(entity_id=entity_id2, a=2, b=4)
        self.version_entity_event_store.append(event2)
        entity_id3 = uuid4()
        event3 = Example.Created(entity_id=entity_id3, a=3, b=6)
        self.version_entity_event_store.append(event3)
        event4 = Example.Discarded(entity_id=entity_id3, entity_version=1)
        self.version_entity_event_store.append(event4)

        # Check the event sourced entities are correct.
        # - just use a trivial mutate that always instantiates the 'Example'.
        event_player = EventPlayer(event_store=self.version_entity_event_store, mutator=Example.mutate)

        # The the reconstituted entity has correct attribute values.
        self.assertEqual(entity_id1, event_player.replay_entity(entity_id1).id)
        self.assertEqual(1, event_player.replay_entity(entity_id1).a)
        self.assertEqual(2, event_player.replay_entity(entity_id2).a)
        self.assertEqual(None, event_player.replay_entity(entity_id3))

        # Check entity3 raises KeyError.
        self.assertEqual(event_player.replay_entity(entity_id3), None)

        # Check it works for "short" entities (should be faster, but the main thing is that it still works).
        # - just use a trivial mutate that always instantiates the 'Example'.
        event5 = Example.AttributeChanged(entity_id=entity_id1, entity_version=1, name='a', value=10)
        self.version_entity_event_store.append(event5)

        event_player = EventPlayer(event_store=self.version_entity_event_store, mutator=Example.mutate)
        self.assertEqual(10, event_player.replay_entity(entity_id1).a)

        event_player = EventPlayer(
            event_store=self.version_entity_event_store,
            mutator=Example.mutate,
            is_short=True,
        )
        self.assertEqual(10, event_player.replay_entity(entity_id1).a)
Exemplo n.º 12
0
    def test_get_domain_events(self):
        event_store = self.construct_event_store()

        # Check there are zero stored events in the repo.
        entity_id1 = uuid4()
        entity_events = event_store.get_domain_events(originator_id=entity_id1)
        entity_events = list(entity_events)
        self.assertEqual(0, len(entity_events))

        # Check there are zero events in the event store, using iterator.
        entity_events = event_store.get_domain_events(originator_id=entity_id1,
                                                      page_size=1)
        entity_events = list(entity_events)
        self.assertEqual(0, len(entity_events))

        # Store a domain event.
        event1 = Example.Created(a=1,
                                 b=2,
                                 originator_id=entity_id1,
                                 originator_topic=get_topic(Example))
        event_store.store(event1)

        # Check there is one event in the event store.
        entity_events = event_store.get_domain_events(originator_id=entity_id1)
        entity_events = list(entity_events)
        self.assertEqual(1, len(entity_events))

        # Check there are two events in the event store, using iterator.
        entity_events = event_store.get_domain_events(originator_id=entity_id1,
                                                      page_size=1)
        entity_events = list(entity_events)
        self.assertEqual(1, len(entity_events))

        # Store another domain event.
        event1 = Example.AttributeChanged(
            a=1,
            b=2,
            originator_id=entity_id1,
            originator_version=1,
        )
        event_store.store(event1)

        # Check there are two events in the event store.
        entity_events = event_store.get_domain_events(originator_id=entity_id1)
        entity_events = list(entity_events)
        self.assertEqual(2, len(entity_events))

        # Check there are two events in the event store, using iterator.
        entity_events = event_store.get_domain_events(originator_id=entity_id1,
                                                      page_size=1)
        entity_events = list(entity_events)
        self.assertEqual(2, len(entity_events))
    def test_get_item(self) -> None:
        # Setup an event store.
        event_store = self.construct_event_store()

        # Put an event in the event store.
        entity_id = uuid4()
        event_store.store_events([
            Example.Created(
                a=1,
                b=2,
                originator_id=entity_id,
                originator_topic=get_topic(Example),
            )
        ])

        # Construct a repository.
        event_sourced_repo: EventSourcedRepository[
            Example,
            Example.Event] = EventSourcedRepository(event_store=event_store)

        # Check the entity attributes.
        example = event_sourced_repo[entity_id]
        self.assertEqual(1, example.a)
        self.assertEqual(2, example.b)
        self.assertEqual(entity_id, example.id)

        # Check class-specific request.
        example = event_sourced_repo.get_instance_of(Example, entity_id)
        self.assertEqual(1, example.a)
        self.assertEqual(2, example.b)
        self.assertEqual(entity_id, example.id)

        # Check class-specific request fails on type.
        class SubExample(Example):
            pass

        self.assertIsNone(
            event_sourced_repo.get_instance_of(SubExample, entity_id))

        # Setup an example repository, using the subclass ExampleRepository.
        example_repo = ExampleRepository(event_store=event_store)

        # Check the repo has the example.
        self.assertIn(entity_id, example_repo)
        self.assertNotIn(uuid4(), example_repo)

        # Check the entity attributes.
        example = example_repo[entity_id]
        self.assertEqual(1, example.a)
        self.assertEqual(2, example.b)
        self.assertEqual(entity_id, example.id)
Exemplo n.º 14
0
    def test_all_domain_events(self):
        event_store = self.construct_event_store()

        # Check there are zero domain events in total.
        domain_events = event_store.all_events()
        domain_events = list(domain_events)
        self.assertEqual(len(domain_events), 0)

        # Store a domain event.
        entity_id1 = uuid4()
        event1 = Example.Created(a=1,
                                 b=2,
                                 originator_id=entity_id1,
                                 originator_topic=get_topic(Example))
        event_store.store_events([event1])

        # Store another domain event for the same entity.
        event1 = Example.AttributeChanged(
            a=1,
            b=2,
            originator_id=entity_id1,
            originator_version=1,
            __previous_hash__=event1.__event_hash__,
        )
        event_store.store_events([event1])

        # Store a domain event for a different entity.
        entity_id2 = uuid4()
        event1 = Example.Created(originator_topic=get_topic(Example),
                                 originator_id=entity_id2,
                                 a=1,
                                 b=2)
        event_store.store_events([event1])

        # Check there are three domain events in total.
        domain_events = event_store.all_events()
        domain_events = list(domain_events)
        self.assertEqual(len(domain_events), 3)
 def test_repr(self):
     entity_id1 = uuid4()
     event1 = Example.Created(originator_id=entity_id1,
                              originator_topic=get_topic(Example),
                              a=1,
                              b=2,
                              timestamp=3)
     self.maxDiff = None
     self.assertEqual((
         "Example.Created(__event_hash__='{}', "
         "__event_topic__='eventsourcing.example.domainmodel#Example.Created', a=1, b=2, "
         "originator_id={}, "
         "originator_topic='eventsourcing.example.domainmodel#Example', originator_version=0, timestamp=3)"
     ).format(event1.__event_hash__, repr(entity_id1)), repr(event1))
Exemplo n.º 16
0
    def test_subscribe_to_decorator(self):
        entity_id1 = uuid4()
        event1 = Example.Created(
            originator_id=entity_id1,
            originator_topic=get_topic(Example),
            a=1, b=2
        )
        event2 = Example.Discarded(
            originator_id=entity_id1,
            originator_version=1,
        )
        handler = mock.Mock()

        # Check we can assert there are no event handlers subscribed.
        assert_event_handlers_empty()

        @subscribe_to(Example.Created)
        def test_handler(e):
            """Doc string"""
            handler(e)

        # Check the decorator doesn't mess with the function doc string.
        self.assertEqual('Doc string', test_handler.__doc__)

        # Check can fail to assert event handlers empty.
        self.assertRaises(EventHandlersNotEmptyError, assert_event_handlers_empty)

        # Check event is received when published individually.
        publish(event1)
        handler.assert_called_once_with(event1)

        # Check event of wrong type is not received.
        handler.reset_mock()
        publish(event2)
        self.assertFalse(handler.call_count)

        # Check a list of events can be filtered.
        handler.reset_mock()
        publish([event1, event2])
        handler.assert_called_once_with(event1)

        handler.reset_mock()
        publish([event1, event1])
        self.assertEqual(2, handler.call_count)

        handler.reset_mock()
        publish([event2, event2])
        self.assertEqual(0, handler.call_count)

        _event_handlers.clear()
Exemplo n.º 17
0
    def test_get_most_recent_event(self):
        event_store = self.construct_event_store()

        # Check there is no most recent event.
        entity_id1 = uuid4()
        entity_event = event_store.get_most_recent_event(entity_id=entity_id1)
        self.assertEqual(entity_event, None)

        # Store a domain event.
        event1 = Example.Created(entity_id=entity_id1, a=1, b=2)
        event_store.append(event1)

        # Check there is an event.
        entity_event = event_store.get_most_recent_event(entity_id=entity_id1)
        self.assertEqual(entity_event, event1)
    def test_get_domain_events_deprecated(self):
        event_store = self.construct_event_store()

        # Check there are zero stored events in the repo.
        entity_id1 = uuid4()
        entity_events = event_store.get_domain_events(originator_id=entity_id1)
        self.assertEqual(0, len(list(entity_events)))

        # Store a domain event.
        event1 = Example.Created(
            a=1, b=2, originator_id=entity_id1, originator_topic=get_topic(Example)
        )
        event_store.store_events([event1])

        # Check there is one event in the event store.
        entity_events = event_store.get_domain_events(originator_id=entity_id1)
        self.assertEqual(1, len(list(entity_events)))
    def test_get_most_recent_event(self):
        event_store = self.construct_event_store()

        # Check there is no most recent event.
        entity_id1 = uuid4()
        entity_event = event_store.get_most_recent_event(originator_id=entity_id1)
        self.assertEqual(entity_event, None)

        # Store a domain event.
        event1 = Example.Created(
            a=1, b=2, originator_id=entity_id1, originator_topic=get_topic(Example)
        )
        event_store.store_events([event1])

        # Check there is an event.
        entity_event = event_store.get_most_recent_event(originator_id=entity_id1)
        self.assertEqual(entity_event, event1)
Exemplo n.º 20
0
    def test_subscribe_to_decorator(self):
        entity_id1 = uuid4()
        event = Example.Created(originator_id=entity_id1, a=1, b=2)
        handler = mock.Mock()

        # Check we can assert there are no event handlers subscribed.
        assert_event_handlers_empty()

        @subscribe_to(Example.Created)
        def test_handler(e):
            handler(e)

        # Check we can assert there are event handlers subscribed.
        self.assertRaises(EventHandlersNotEmptyError,
                          assert_event_handlers_empty)

        # Check what happens when an event is published.
        publish(event)
        handler.assert_called_once_with(event)
 def test_repr(self):
     entity_id1 = UUID('c7383095-85a3-4c49-ae32-9c9957ac8579')
     event1 = Example.Created(
         originator_id=entity_id1,
         originator_topic=get_topic(Example),
         a=1,
         b=2,
         timestamp=3,
     )
     self.maxDiff = None
     self.assertEqual(
         ("Example.Created("
          "__event_hash__='dbd0d45ed797de4f9a5d574ec4e3da3df74e67641bd7632dd05ffa28a5876391', "
          "__event_hash_method_name__='__hash_object_v2__', "
          "__event_topic__='eventsourcing.example.domainmodel#Example.Created', a=1, b=2, "
          "originator_id={}, "
          "originator_topic='eventsourcing.example.domainmodel#Example', originator_version=0, timestamp=3)"
          ).format(repr(entity_id1)),
         repr(event1),
     )
    def test_subscribe_to_decorator(self):
        entity_id1 = uuid4()
        event1 = Example.Created(originator_id=entity_id1,
                                 originator_topic=get_topic(Example),
                                 a=1,
                                 b=2)
        event2 = Example.Discarded(originator_id=entity_id1,
                                   originator_version=1)
        handler1 = mock.Mock()
        handler2 = mock.Mock()
        handler3 = mock.Mock()

        # Check we can assert there are no event handlers subscribed.
        assert_event_handlers_empty()

        # Original style (one event class arg).
        @subscribe_to(Example.Created)
        def test_handler1(e):
            """Doc string"""
            handler1(e)

        # Naked style (not called).
        @subscribe_to
        def test_handler2(e):
            """Doc string"""
            handler2(e)

        # Multi-event style (many event class args).
        @subscribe_to((Example.Created, Example.Discarded))
        def test_handler3(e):
            """Doc string"""
            handler3(e)

        # Check the decorator doesn't mess with the function doc string.
        self.assertEqual("Doc string", test_handler1.__doc__)
        self.assertEqual("Doc string", test_handler2.__doc__)
        self.assertEqual("Doc string", test_handler3.__doc__)

        # Check can fail to assert event handlers empty.
        self.assertRaises(EventHandlersNotEmptyError,
                          assert_event_handlers_empty)

        # Check event is received when published individually.
        publish([event1])
        handler1.assert_called_once_with(event1)
        handler2.assert_called_once_with(event1)
        handler3.assert_called_once_with(event1)

        # Check event of wrong type is not received.
        handler1.reset_mock()
        handler2.reset_mock()
        handler3.reset_mock()
        publish([event2])
        self.assertFalse(handler1.call_count)
        handler2.assert_called_once_with(event2)
        handler3.assert_called_once_with(event2)

        # Check a list of events can be filtered.
        handler1.reset_mock()
        handler2.reset_mock()
        handler3.reset_mock()
        publish([event1, event2])
        handler1.assert_called_once_with(event1)
        self.assertEqual(handler2.call_count, 2)
        self.assertEqual(handler3.call_count, 2)

        handler1.reset_mock()
        handler2.reset_mock()
        handler3.reset_mock()
        publish([event1, event1])
        self.assertEqual(2, handler1.call_count)
        self.assertEqual(2, handler2.call_count)
        self.assertEqual(2, handler3.call_count)

        handler1.reset_mock()
        handler2.reset_mock()
        handler3.reset_mock()
        publish([event2, event2])
        self.assertEqual(0, handler1.call_count)
        self.assertEqual(2, handler2.call_count)
        self.assertEqual(2, handler3.call_count)

        clear_event_handlers()
Exemplo n.º 23
0
    def test_entity_lifecycle(self):
        # Check the factory creates an instance.
        example1 = Example.__create__(a=1, b=2)

        self.assertIsInstance(example1, Example)

        # Check the instance is equal to itself.
        self.assertEqual(example1, example1)

        # Check the instance is equal to a clone of itself.
        clone = object.__new__(type(example1))
        clone.__dict__.update(example1.__dict__)
        self.assertEqual(example1, clone)

        # Check the properties of the Example class.
        self.assertEqual(1, example1.a)
        self.assertEqual(2, example1.b)

        # Check the properties of the TimestampedVersionedEntity class.
        self.assertTrue(example1.id)
        self.assertEqual(example1.__version__, 0)
        self.assertTrue(example1.__created_on__)
        self.assertLess(example1.__created_on__, time.time())
        self.assertGreater(example1.__created_on__, time.time() - 1)
        self.assertTrue(example1.__last_modified__)
        self.assertEqual(example1.__created_on__, example1.__last_modified__)

        # Test the datetime_from_timestamp() converts ok.
        tt = time.time()
        dt = datetime.datetime.utcnow()
        self.assertEqual(datetime_from_timestamp(tt).hour, dt.hour)

        # Check can get datetime from timestamps, and it corresponds to UTC.
        dt = datetime_from_timestamp(example1.__created_on__)
        self.assertLess(dt, datetime.datetime.utcnow())
        self.assertGreater(dt,
                           datetime.datetime.utcnow() - datetime.timedelta(1))

        # Check a different type with the same values is not "equal" to the first.
        class Subclass(Example):
            pass

        other = object.__new__(Subclass)
        other.__dict__.update(example1.__dict__)
        self.assertEqual(example1.__dict__, other.__dict__)
        self.assertNotEqual(example1, other)

        # Check a second instance with the same values is not "equal" to the first.
        example2 = create_new_example(a=1, b=2)
        self.assertEqual(type(example1), type(example2))
        self.assertNotEqual(example1, example2)

        # Check entity not hashable.
        with self.assertRaises(TypeError):
            hash(example1)

        # Setup the repo.
        repo = ExampleRepository(self.entity_event_store)

        # Check the example entities can be retrieved from the example repository.
        entity1 = repo[example1.id]
        self.assertIsInstance(entity1, Example)
        self.assertEqual(1, entity1.a)
        self.assertEqual(2, entity1.b)

        entity2 = repo[example2.id]
        self.assertIsInstance(entity2, Example)
        self.assertEqual(1, entity2.a)
        self.assertEqual(2, entity2.b)

        # Check the entity can be updated.
        entity1.a = 100
        self.assertEqual(100, repo[entity1.id].a)
        entity1.b = -200
        self.assertEqual(-200, repo[entity1.id].b)

        self.assertEqual(repo[entity1.id].__created_on__,
                         entity1.__created_on__)
        self.assertEqual(repo[entity1.id].__last_modified__,
                         entity1.__last_modified__)
        self.assertNotEqual(entity1.__last_modified__, entity1.__created_on__)

        self.assertEqual(0, entity1.count_heartbeats())
        entity1.beat_heart()
        entity1.beat_heart()
        entity1.beat_heart()
        self.assertEqual(3, entity1.count_heartbeats())
        self.assertEqual(3, repo[entity1.id].count_heartbeats())

        # Check the entity can publish multiple events simultaneously.
        entity1.beat_heart(number_of_beats=3)
        self.assertEqual(6, repo[entity1.id].count_heartbeats())

        # Check the entity can be discarded.
        entity1.__discard__()

        # Check the repo now raises a KeyError.
        self.assertRaises(RepositoryKeyError, repo.__getitem__, entity1.id)

        # Check the entity can't be discarded twice.
        self.assertRaises(AssertionError, entity1.__discard__)

        # Should fail to validate event with wrong entity ID.
        with self.assertRaises(OriginatorIDError):
            VersionedEntity.Event(
                originator_id=uuid4(),
                originator_version=0,
            ).__check_obj__(entity2)
        # Should fail to validate event with wrong entity version.
        with self.assertRaises(OriginatorVersionError):
            VersionedEntity.Event(
                originator_id=entity2.id,
                originator_version=0,
                __previous_hash__=entity2.__head__,
            ).__check_obj__(entity2)

        # Should validate event with correct entity ID and version.
        VersionedEntity.Event(
            originator_id=entity2.id,
            originator_version=entity2.__version__ + 1,
            __previous_hash__=entity2.__head__,
        ).__check_obj__(entity2)

        # Check an entity cannot be reregistered with the ID of a discarded entity.
        replacement_event = Example.Created(
            originator_id=entity1.id,
            a=11,
            b=12,
            originator_topic=get_topic(Example),
        )
        with self.assertRaises(ConcurrencyError):
            publish(event=replacement_event)
Exemplo n.º 24
0
    def test_entity_lifecycle(self):
        # Check the factory creates an instance.
        example1 = create_new_example(a=1, b=2)
        self.assertIsInstance(example1, Example)

        # Check the instance is equal to itself.
        self.assertEqual(example1, example1)

        # Check the instance is equal to a clone of itself.
        clone = object.__new__(type(example1))
        clone.__dict__.update(example1.__dict__)
        self.assertEqual(example1, clone)

        # Check the properties of the Example class.
        self.assertEqual(1, example1.a)
        self.assertEqual(2, example1.b)

        # Check the properties of the TimestampedVersionedEntity class.
        self.assertTrue(example1.id)
        self.assertEqual(1, example1.version)
        self.assertTrue(example1.created_on)
        self.assertTrue(example1.last_modified)
        self.assertEqual(example1.created_on, example1.last_modified)

        # Check a different type with the same values is not "equal" to the first.
        class Subclass(Example):
            pass

        other = object.__new__(Subclass)
        other.__dict__.update(example1.__dict__)
        self.assertEqual(example1.__dict__, other.__dict__)
        self.assertNotEqual(example1, other)

        # Check a second instance with the same values is not "equal" to the first.
        example2 = create_new_example(a=1, b=2)
        self.assertEqual(type(example1), type(example2))
        self.assertNotEqual(example1, example2)

        # Setup the repo.
        repo = ExampleRepository(self.entity_event_store)

        # Check the example entities can be retrieved from the example repository.
        entity1 = repo[example1.id]
        self.assertIsInstance(entity1, Example)
        self.assertEqual(1, entity1.a)
        self.assertEqual(2, entity1.b)

        entity2 = repo[example2.id]
        self.assertIsInstance(entity2, Example)
        self.assertEqual(1, entity2.a)
        self.assertEqual(2, entity2.b)

        # Check the entity can be updated.
        entity1.a = 100
        self.assertEqual(100, repo[entity1.id].a)
        entity1.b = -200
        self.assertEqual(-200, repo[entity1.id].b)

        self.assertEqual(repo[entity1.id].created_on, entity1.created_on)
        self.assertEqual(repo[entity1.id].last_modified, entity1.last_modified)
        self.assertNotEqual(entity1.last_modified, entity1.created_on)

        self.assertEqual(0, entity1.count_heartbeats())
        entity1.beat_heart()
        entity1.beat_heart()
        entity1.beat_heart()
        self.assertEqual(3, entity1.count_heartbeats())
        self.assertEqual(3, repo[entity1.id].count_heartbeats())

        # Check the entity can publish multiple events simultaneously.
        entity1.beat_heart(number_of_beats=3)
        self.assertEqual(6, repo[entity1.id].count_heartbeats())

        # Check the entity can be discarded.
        entity1.discard()

        # Check the repo now raises a KeyError.
        self.assertRaises(RepositoryKeyError, repo.__getitem__, entity1.id)

        # Check the entity can't be discarded twice.
        self.assertRaises(AssertionError, entity1.discard)

        # Should fail to validate event with wrong entity ID.
        with self.assertRaises(MismatchedOriginatorIDError):
            entity2._validate_originator(
                VersionedEntity.Event(originator_id=uuid4(),
                                      originator_version=0))
        # Should fail to validate event with wrong entity version.
        with self.assertRaises(MismatchedOriginatorVersionError):
            entity2._validate_originator(
                VersionedEntity.Event(
                    originator_id=entity2.id,
                    originator_version=0,
                ))

        # Should validate event with correct entity ID and version.
        entity2._validate_originator(
            VersionedEntity.Event(
                originator_id=entity2.id,
                originator_version=entity2.version,
            ))

        # Check an entity cannot be reregistered with the ID of a discarded entity.
        replacement_event = Example.Created(originator_id=entity1.id,
                                            a=11,
                                            b=12)
        with self.assertRaises(ConcurrencyError):
            publish(event=replacement_event)