コード例 #1
0
    def test(self):

        # Define fixture that receives prompts.
        class FollowerFixture(RecordingEventReceiver):
            def __init__(self):
                self.num_received = 0

            def receive_recording_event(
                    self, recording_event: RecordingEvent) -> None:
                self.num_received += 1

        # Test fixture is working.
        follower = FollowerFixture()
        follower.receive_recording_event(RecordingEvent("Leader", [], 1))
        self.assertEqual(follower.num_received, 1)

        # Construct leader.
        leader = Leader()
        leader.lead(follower)

        # Check follower receives a prompt when there are new events.
        leader.save(Aggregate())
        self.assertEqual(follower.num_received, 2)

        # Check follower doesn't receive prompt when no new events.
        leader.save()
        self.assertEqual(follower.num_received, 2)

        # Check follower doesn't receive prompt when recordings are filtered out.
        leader.notify_topics = ["topic1"]
        leader.save(Aggregate())
        self.assertEqual(follower.num_received, 2)
コード例 #2
0
    def test_trigger_event(self):
        a = Aggregate()

        # Check the aggregate can trigger further events.
        a.trigger_event(AggregateEvent)
        self.assertLess(a.created_on, a.modified_on)

        pending = a.collect_events()
        self.assertEqual(len(pending), 2)
        self.assertIsInstance(pending[0], AggregateCreated)
        self.assertEqual(pending[0].originator_version, 1)
        self.assertIsInstance(pending[1], AggregateEvent)
        self.assertEqual(pending[1].originator_version, 2)
コード例 #3
0
    def test_call_base_class(self):
        before_created = datetime.now(tz=TZINFO)
        a = Aggregate()
        after_created = datetime.now(tz=TZINFO)
        self.assertIsInstance(a, Aggregate)
        self.assertIsInstance(a.id, UUID)
        self.assertIsInstance(a.version, int)
        self.assertEqual(a.version, 1)
        self.assertIsInstance(a.created_on, datetime)
        self.assertIsInstance(a.modified_on, datetime)
        self.assertEqual(a.created_on, a.modified_on)
        self.assertGreater(a.created_on, before_created)
        self.assertGreater(after_created, a.created_on)

        events = a.collect_events()
        self.assertIsInstance(events[0], AggregateCreated)
        self.assertEqual("Aggregate.Created", type(events[0]).__qualname__)
コード例 #4
0
    def test_repr_baseclass(self):
        a = Aggregate()

        expect = (f"Aggregate(id={a.id!r}, "
                  "version=1, "
                  f"created_on={a.created_on!r}, "
                  f"modified_on={a.modified_on!r}"
                  ")")
        self.assertEqual(expect, repr(a))

        a.trigger_event(AggregateEvent)

        expect = (f"Aggregate(id={a.id!r}, "
                  "version=2, "
                  f"created_on={a.created_on!r}, "
                  f"modified_on={a.modified_on!r}"
                  ")")
        self.assertEqual(expect, repr(a))
コード例 #5
0
    def test_contains(self):
        transcoder = JSONTranscoder()
        transcoder.register(UUIDAsHex())
        transcoder.register(DecimalAsStr())
        transcoder.register(DatetimeAsISO())

        event_recorder = POPOAggregateRecorder()
        event_store = EventStore(
            mapper=Mapper(transcoder=transcoder),
            recorder=event_recorder,
        )

        aggregate = Aggregate()
        event_store.put(aggregate.collect_events())

        repository = Repository(event_store)
        self.assertTrue(aggregate.id in repository)
        self.assertFalse(uuid4() in repository)
コード例 #6
0
    def test_save_returns_recording_event(self):
        app = Application()

        recordings = app.save()
        self.assertEqual(recordings, [])

        recordings = app.save(None)
        self.assertEqual(recordings, [])

        recordings = app.save(Aggregate())
        self.assertEqual(len(recordings), 1)
        self.assertEqual(recordings[0].notification.id, 1)

        recordings = app.save(Aggregate())
        self.assertEqual(len(recordings), 1)
        self.assertEqual(recordings[0].notification.id, 2)

        recordings = app.save(Aggregate(), Aggregate())
        self.assertEqual(len(recordings), 2)
        self.assertEqual(recordings[0].notification.id, 3)
        self.assertEqual(recordings[1].notification.id, 4)
コード例 #7
0
    def test_event_mutate_raises_version_error(self):
        a = Aggregate()

        # Try to mutate aggregate with an invalid domain event.
        event = AggregateEvent(
            originator_id=a.id,
            originator_version=a.version,  # NB not +1.
            timestamp=datetime.now(tz=TZINFO),
        )
        # Check raises "VersionError".
        with self.assertRaises(VersionError):
            event.mutate(a)
コード例 #8
0
    def test_event_mutate_raises_originator_id_error(self):
        a = Aggregate()

        # Try to mutate aggregate with an invalid domain event.
        event = AggregateEvent(
            originator_id=uuid4(),
            originator_version=a.version + 1,
            timestamp=AggregateEvent.create_timestamp(),
        )
        # Check raises "VersionError".
        with self.assertRaises(OriginatorIDError):
            event.mutate(a)
コード例 #9
0
    def test_cache_raises_aggregate_not_found_when_projector_func_returns_none(
            self):
        transcoder = JSONTranscoder()
        transcoder.register(UUIDAsHex())
        transcoder.register(DecimalAsStr())
        transcoder.register(DatetimeAsISO())
        transcoder.register(EmailAddressAsStr())

        event_recorder = SQLiteAggregateRecorder(SQLiteDatastore(":memory:"))
        event_recorder.create_table()
        event_store = EventStore(
            mapper=Mapper(transcoder=transcoder),
            recorder=event_recorder,
        )
        repository = Repository(
            event_store,
            cache_maxsize=2,
        )

        aggregate = Aggregate()
        event_store.put(aggregate.collect_events())
        self.assertEqual(1, repository.get(aggregate.id).version)

        aggregate.trigger_event(Aggregate.Event)
        event_store.put(aggregate.collect_events())
        with self.assertRaises(AggregateNotFound):
            repository.get(aggregate.id, projector_func=lambda _, __: None)
コード例 #10
0
    def test_cache_fastforward_false(self):
        transcoder = JSONTranscoder()
        transcoder.register(UUIDAsHex())
        transcoder.register(DecimalAsStr())
        transcoder.register(DatetimeAsISO())
        transcoder.register(EmailAddressAsStr())

        event_recorder = SQLiteAggregateRecorder(SQLiteDatastore(":memory:"))
        event_recorder.create_table()
        event_store = EventStore(
            mapper=Mapper(transcoder=transcoder),
            recorder=event_recorder,
        )
        repository = Repository(
            event_store,
            cache_maxsize=2,
            fastforward=False,
        )

        aggregate = Aggregate()
        event_store.put(aggregate.collect_events())
        self.assertEqual(1, repository.get(aggregate.id).version)

        aggregate.trigger_event(Aggregate.Event)
        event_store.put(aggregate.collect_events())
        self.assertEqual(1, repository.get(aggregate.id).version)
コード例 #11
0
 def test_call_class_method_create(self):
     # Check the _create() method creates a new aggregate.
     before_created = datetime.now(tz=TZINFO)
     uuid = uuid4()
     a = Aggregate._create(
         event_class=AggregateCreated,
         id=uuid,
     )
     after_created = datetime.now(tz=TZINFO)
     self.assertIsInstance(a, Aggregate)
     self.assertEqual(a.id, uuid)
     self.assertEqual(a.version, 1)
     self.assertEqual(a.created_on, a.modified_on)
     self.assertGreater(a.created_on, before_created)
     self.assertGreater(after_created, a.created_on)
コード例 #12
0
    def test(self):
        app = BankAccountsWithAutomaticSnapshotting()

        # Check snapshotting is enabled by setting snapshotting_intervals only.
        self.assertTrue(app.snapshots)

        # Open an account.
        account_id = app.open_account("Alice", "*****@*****.**")

        # Check there are no snapshots.
        snapshots = list(app.snapshots.get(account_id))
        self.assertEqual(len(snapshots), 0)

        # Trigger twelve more events.
        for _ in range(12):
            app.credit_account(account_id, Decimal("10.00"))

        # Check the account is at version 13.
        account = app.get_account(account_id)
        self.assertEqual(account.version, 13)

        # Check snapshots have been taken at regular intervals.
        snapshots = list(app.snapshots.get(account_id))
        self.assertEqual(len(snapshots), 2)
        self.assertEqual(snapshots[0].originator_version, 5)
        self.assertEqual(snapshots[1].originator_version, 10)

        # Check another type of aggregate is not snapshotted.
        aggregate = Aggregate()
        for _ in range(10):
            aggregate.trigger_event(Aggregate.Event)
        app.save(aggregate)

        # Check snapshots have not been taken at regular intervals.
        snapshots = list(app.snapshots.get(aggregate.id))
        self.assertEqual(len(snapshots), 0)
コード例 #13
0
    def test_application_with_cached_aggregates(self):
        app = Application(env={"AGGREGATE_CACHE_MAXSIZE": "10"})

        aggregate = Aggregate()
        app.save(aggregate)
        self.assertEqual(aggregate, app.repository.cache.get(aggregate.id))
コード例 #14
0
 def create_aggregate(self) -> UUID:
     aggregate = Aggregate()
     logged_id = self.aggregate_log.trigger_event(
         aggregate_id=aggregate.id)
     self.save(aggregate, logged_id)
     return aggregate.id
コード例 #15
0
    def test_cache_maxsize_nonzero(self):
        transcoder = JSONTranscoder()
        transcoder.register(UUIDAsHex())
        transcoder.register(DecimalAsStr())
        transcoder.register(DatetimeAsISO())
        transcoder.register(EmailAddressAsStr())

        event_recorder = SQLiteAggregateRecorder(SQLiteDatastore(":memory:"))
        event_recorder.create_table()
        event_store = EventStore(
            mapper=Mapper(transcoder=transcoder),
            recorder=event_recorder,
        )
        repository = Repository(event_store, cache_maxsize=2)
        self.assertEqual(type(repository.cache), LRUCache)

        aggregate1 = Aggregate()
        self.assertFalse(aggregate1.id in repository)
        event_store.put(aggregate1.collect_events())
        self.assertTrue(aggregate1.id in repository)

        aggregate2 = Aggregate()
        self.assertFalse(aggregate2.id in repository)
        event_store.put(aggregate2.collect_events())
        self.assertTrue(aggregate2.id in repository)

        aggregate3 = Aggregate()
        self.assertFalse(aggregate3.id in repository)
        event_store.put(aggregate3.collect_events())
        self.assertTrue(aggregate3.id in repository)

        self.assertFalse(aggregate1.id in repository.cache.cache)

        self.assertEqual(1, repository.get(aggregate1.id).version)
        self.assertEqual(1, repository.get(aggregate2.id).version)
        self.assertEqual(1, repository.get(aggregate3.id).version)

        aggregate1.trigger_event(Aggregate.Event)
        event_store.put(aggregate1.collect_events())
        self.assertEqual(2, repository.get(aggregate1.id).version)