def test_upcast_created_event_from_v4(self): app = Application() aggregate = self.UpcastFixtureV4.create(A="TEXT", b=1, c=[1, 2]) app.save(aggregate) copy = app.repository.get(aggregate.id) self.assertFalse(hasattr(copy, "a")) self.assertEqual(copy.A, "TEXT") self.assertEqual(copy.b, 1) self.assertEqual(copy.c, [1, 2]) self.assertEqual(copy.d, None)
def test_take_snapshot_raises_assertion_error_if_snapshotting_not_enabled( self): app = Application() with self.assertRaises(AssertionError) as cm: app.take_snapshot(uuid4()) self.assertEqual( cm.exception.args[0], ("Can't take snapshot without snapshots store. " "Please set environment variable IS_SNAPSHOTTING_ENABLED " "to a true value (e.g. 'y')."), )
def test_take_snapshot_raises_assertion_error_if_snapshotting_not_enabled( self): app = Application() with self.assertRaises(AssertionError) as cm: app.take_snapshot(uuid4()) self.assertEqual( cm.exception.args[0], ("Can't take snapshot without snapshots store. Please " "set environment variable IS_SNAPSHOTTING_ENABLED to " "a true value (e.g. 'y'), or set 'is_snapshotting_enabled' " "on application class, or set 'snapshotting_intervals' on " "application class."), )
def test_event_decorator_uses_explicit_event_classes(self) -> None: # Here we just use the @event decorator to trigger events # that are applied using the decorated method. @aggregate class Order: class Confirmed(AggregateEvent): at: datetime @triggers(Confirmed) def confirm(self, at): self.confirmed_at = at order = Order() order.confirm(datetime.now()) self.assertIsInstance(order.confirmed_at, datetime) app: Application = Application() app.save(order) copy = app.repository.get(order.id) self.assertEqual(copy.confirmed_at, order.confirmed_at) self.assertIsInstance(order, Aggregate) self.assertIsInstance(order, Order) self.assertIsInstance(copy, Aggregate) self.assertIsInstance(copy, Order)
def test(self) -> None: invoice = Invoice( number="INV/2021/11/01", amount=Decimal("34.20"), issued_to=Person("Oscar the Grouch", "123 Sesame Street"), ) self.assertEqual(invoice.number, "INV/2021/11/01") self.assertEqual(invoice.amount, Decimal("34.20")) self.assertEqual(invoice.issued_to, Person("Oscar the Grouch", "123 Sesame Street")) self.assertEqual(invoice.status, Status.INITIATED) invoice.number = "INV/2021/11/02" # type: ignore self.assertEqual(invoice.number, "INV/2021/11/02") invoice.amount = Decimal("43.20") # type: ignore self.assertEqual(invoice.number, "INV/2021/11/02") invoice.issue(issued_by="Cookie Monster") self.assertEqual(invoice.issued_by, "Cookie Monster") self.assertEqual(invoice.status, Status.ISSUED) with self.assertRaises(AssertionError): invoice.number = "INV/2021/11/03" # type: ignore with self.assertRaises(AssertionError): invoice.amount = Decimal("54.20") # type: ignore invoice.send(sent_via=SendMethod.EMAIL) self.assertEqual(invoice.sent_via, SendMethod.EMAIL) self.assertEqual(invoice.status, Status.SENT) app: Application = Application(env={"IS_SNAPSHOTTING_ENABLED": "y"}) app.mapper.transcoder.register(PersonAsDict()) app.mapper.transcoder.register(SendMethodAsStr()) app.mapper.transcoder.register(StatusAsStr()) app.save(invoice) copy = app.repository.get(invoice.id) self.assertEqual(invoice, copy) assert app.snapshots is not None snapshots = list(app.snapshots.get(invoice.id)) self.assertEqual(len(snapshots), 0) app.take_snapshot(invoice.id) copy = app.repository.get(invoice.id) self.assertEqual(invoice, copy) copy = app.repository.get(invoice.id, version=1) self.assertNotEqual(invoice, copy) snapshots = list(app.snapshots.get(invoice.id)) self.assertEqual(len(snapshots), 1) snapshot = snapshots[0] copy2 = snapshot.mutate(None) self.assertEqual(invoice, copy2)
def test_upcast_created_event_from_v1(self): app = Application() topic_v1 = get_topic(self.UpcastFixtureV1) topic_v1_created = get_topic(self.UpcastFixtureV1.Created) aggregate = self.UpcastFixtureV1.create(a="text") app.save(aggregate) copy = app.repository.get(aggregate.id) self.assertEqual(copy.a, "text") self.assertFalse(hasattr(copy, "b")) self.assertFalse(hasattr(copy, "c")) self.assertFalse(hasattr(copy, "d")) # "Deploy" v2. del _topic_cache[topic_v1] del _topic_cache[topic_v1_created] type(self).UpcastFixtureV1 = self.UpcastFixtureV2 copy = app.repository.get(aggregate.id) self.assertFalse(hasattr(copy, "a")) self.assertEqual(copy.A, "TEXT") self.assertEqual(copy.b, 0) self.assertFalse(hasattr(copy, "c")) self.assertFalse(hasattr(copy, "d")) # "Deploy" v3. del _topic_cache[topic_v1] del _topic_cache[topic_v1_created] type(self).UpcastFixtureV1 = self.UpcastFixtureV3 copy = app.repository.get(aggregate.id) self.assertFalse(hasattr(copy, "a")) self.assertEqual(copy.A, "TEXT") self.assertEqual(copy.b, 0) self.assertEqual(copy.c, []) # "Deploy" v4. del _topic_cache[topic_v1] type(self).UpcastFixtureV1 = self.UpcastFixtureV4 copy = app.repository.get(aggregate.id) self.assertFalse(hasattr(copy, "a")) self.assertEqual(copy.A, "TEXT") self.assertEqual(copy.b, 0) self.assertEqual(copy.c, []) self.assertEqual(copy.d, None)
def test_upcast_aggregate_snapshot_from_v3(self): app = Application() topic_v3 = get_topic(self.UpcastFixtureV3) aggregate = self.UpcastFixtureV3.create(A="TEXT", b=1, c=[1, 2]) app.save(aggregate) copy = app.repository.get(aggregate.id) self.assertFalse(hasattr(copy, "a")) self.assertEqual(copy.A, "TEXT") self.assertEqual(copy.b, 1) self.assertEqual(copy.c, [1, 2]) self.assertFalse(hasattr(copy, "d")) app.take_snapshot(aggregate.id) # "Deploy" v3. del _topic_cache[topic_v3] type(self).UpcastFixtureV3 = self.UpcastFixtureV4 copy = app.repository.get(aggregate.id) self.assertFalse(hasattr(copy, "a")) self.assertEqual(copy.A, "TEXT") self.assertEqual(copy.b, 1) self.assertEqual(copy.c, [1, 2]) self.assertEqual(copy.d, None) copy.set_d(value=Decimal("10.0")) app.save(copy) copy = app.repository.get(aggregate.id) self.assertFalse(hasattr(copy, "a")) self.assertEqual(copy.A, "TEXT") self.assertEqual(copy.b, 1) self.assertEqual(copy.c, [1, 2]) self.assertEqual(copy.d, 10) app.take_snapshot(aggregate.id) copy = app.repository.get(aggregate.id) self.assertFalse(hasattr(copy, "a")) self.assertEqual(copy.A, "TEXT") self.assertEqual(copy.b, 1) self.assertEqual(copy.c, [1, 2]) self.assertEqual(copy.d, 10)
def test_application_log(self): # Check the old 'log' attribute presents the 'notification log' object. app = Application() with warnings.catch_warnings(record=True) as w: self.assertIs(app.log, app.notification_log) # Verify deprecation warning. assert len(w) == 1 assert issubclass(w[-1].category, DeprecationWarning) assert "'log' is deprecated, use 'notifications' instead" in str( w[-1].message)
def test_upcast_created_event_from_v2(self): app = Application() topic_v2 = get_topic(self.UpcastFixtureV2) topic_v2_created = get_topic(self.UpcastFixtureV2.Created) aggregate = self.UpcastFixtureV2.create(A="TEXT", b=1) app.save(aggregate) copy = app.repository.get(aggregate.id) self.assertFalse(hasattr(copy, "a")) self.assertEqual(copy.A, "TEXT") self.assertEqual(copy.b, 1) self.assertFalse(hasattr(copy, "c")) self.assertFalse(hasattr(copy, "d")) # "Deploy" v3. del _topic_cache[topic_v2] del _topic_cache[topic_v2_created] type(self).UpcastFixtureV2 = self.UpcastFixtureV3 copy = app.repository.get(aggregate.id) self.assertFalse(hasattr(copy, "a")) self.assertEqual(copy.A, "TEXT") self.assertEqual(copy.b, 1) self.assertEqual(copy.c, []) self.assertFalse(hasattr(copy, "d")) # "Deploy" v4. del _topic_cache[topic_v2] del _topic_cache[topic_v2_created] type(self).UpcastFixtureV2 = self.UpcastFixtureV4 copy = app.repository.get(aggregate.id) self.assertFalse(hasattr(copy, "a")) self.assertEqual(copy.A, "TEXT") self.assertEqual(copy.b, 1) self.assertEqual(copy.c, []) self.assertEqual(copy.d, None)
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)
def test_resolve_persistence_topics(self): # None specified. app = Application() self.assertIsInstance(app.factory, InfrastructureFactory) # Legacy 'INFRASTRUCTURE_FACTORY'. app = Application( env={"INFRASTRUCTURE_FACTORY": "eventsourcing.popo:Factory"}) self.assertIsInstance(app.factory, InfrastructureFactory) # Legacy 'FACTORY_TOPIC'. app = Application(env={"FACTORY_TOPIC": "eventsourcing.popo:Factory"}) self.assertIsInstance(app.factory, InfrastructureFactory) # Check 'PERSISTENCE_MODULE' resolves to a class. app = Application(env={"PERSISTENCE_MODULE": "eventsourcing.popo"}) self.assertIsInstance(app.factory, InfrastructureFactory) # Check exceptions. with self.assertRaises(AssertionError) as cm: Application( env={"PERSISTENCE_MODULE": "eventsourcing.application"}) self.assertEqual( cm.exception.args[0], ("Found 0 infrastructure factory classes in " "'eventsourcing.application', expected 1."), ) with self.assertRaises(AssertionError) as cm: Application(env={ "PERSISTENCE_MODULE": "eventsourcing.application:Application" }) self.assertEqual( cm.exception.args[0], ("Not an infrastructure factory class or module: " "eventsourcing.application:Application"), )
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))