def test_uow_can_be_initiated_explicitly(self, test_domain): uow = UnitOfWork() assert uow is not None assert uow.in_progress is False uow.start() assert uow.in_progress is True
def test_expected_version_error(test_domain): identifier = str(uuid4()) with UnitOfWork(): repo = test_domain.repository_for(User) user = User.register( user_id=identifier, name="John Doe", email="*****@*****.**" ) repo.add(user) user_dup1 = repo.get(identifier) user_dup2 = repo.get(identifier) with UnitOfWork(): user_dup1.activate() repo.add(user_dup1) with pytest.raises(ExpectedVersionError) as exc: with UnitOfWork(): user_dup2.change_name("Mike") repo.add(user_dup2) assert ( exc.value.args[0] == f"Wrong expected version: 0 (Stream: user-{identifier}, Stream Version: 1)" )
def test_that_uow_can_be_started_manually(self, test_domain): uow = UnitOfWork() uow.start() uow.commit() # `commit` should not raise exception uow.start() uow.rollback() # `rollback` should not raise exception
def test_changed_objects_are_committed_as_part_of_one_transaction( self, test_domain): # Add a Person the database repo = test_domain.repository_for(Person) person_to_be_updated = self.persisted_person(test_domain) repo.add(person_to_be_updated) person_dao = test_domain.repository_for(Person)._dao # Initiate a UnitOfWork Session with UnitOfWork(): repo_with_uow = test_domain.repository_for(Person) # Create a new person object to be added person_to_be_added = Person(first_name="John", last_name="Doe") repo_with_uow.add(person_to_be_added) # Update an existing Person record person_to_be_updated.last_name = "FooBar" repo_with_uow.add(person_to_be_updated) # Test that the underlying database is untouched assert len(person_dao.query.all().items) == 2 assert (person_dao.outside_uow().get( person_to_be_updated.id).last_name != "FooBar") assert len(person_dao.query.all().items) == 2 assert person_dao.get(person_to_be_added.id) is not None assert person_dao.get(person_to_be_updated.id).last_name == "FooBar"
def add(cls, command: PersonCommand): with UnitOfWork(): newcomer = Person.add_newcomer(command.to_dict()) person_repo = current_domain.repository_for(Person) person_repo.add(newcomer) return newcomer
def test_all_changes_are_discarded_on_rollback(self, test_domain): repo = test_domain.repository_for(Person) person_to_be_updated = self.persisted_person(test_domain) repo.add(person_to_be_updated) person_dao = test_domain.repository_for(Person)._dao # Initiate a UnitOfWork Session uow = UnitOfWork() uow.start() repo_with_uow = test_domain.repository_for(Person) # Create a new person object to be added person_to_be_added = Person(first_name="John", last_name="Doe") repo_with_uow.add(person_to_be_added) # Update an existing Person record person_to_be_updated.last_name = "FooBar" repo_with_uow.add(person_to_be_updated) # Test that the underlying database is untouched assert len(person_dao.outside_uow().query.all().items) == 1 assert (person_dao.outside_uow().get(person_to_be_updated.id).last_name != "FooBar") uow.rollback() assert uow.in_progress is False assert len(person_dao.query.all().items) == 1 assert person_dao.get(person_to_be_updated.id).last_name != "FooBar"
def test_session_is_destroyed_after_rollback(self, test_domain): uow = UnitOfWork() uow.start() uow.rollback() assert uow._sessions == {} assert uow.in_progress is False
def test_that_snapshot_is_constructed_after_threshold(test_domain): identifier = str(uuid4()) repo = test_domain.repository_for(User) with UnitOfWork(): user = User.register(user_id=identifier, name="John Doe", email="*****@*****.**") user.activate() repo.add(user) for i in range(3, test_domain.config["SNAPSHOT_THRESHOLD"] + 2): # Start at 3 because we already have two events with UnitOfWork(): user = repo.get(identifier) user.change_name(f"John Doe {i}") repo.add(user) snapshot = test_domain.event_store.store._read_last_message( f"user:snapshot-{identifier}") assert snapshot is not None assert User(**snapshot["data"]) == user assert snapshot["data"]["name"] == "John Doe 10"
def test_that_a_new_stream_has_no_snapshot(test_domain): identifier = str(uuid4()) repo = test_domain.repository_for(User) with UnitOfWork(): user = User.register(user_id=identifier, name="John Doe", email="*****@*****.**") user.activate() repo.add(user) snapshot = test_domain.event_store.store._read_last_message( f"user:snapshot-{identifier}") assert snapshot is None
def test_that_a_stream_with_a_snapshop_and_no_further_events_is_reconstructed_correctly( test_domain, ): identifier = str(uuid4()) repo = test_domain.repository_for(User) with UnitOfWork(): user = User.register(user_id=identifier, name="John Doe", email="*****@*****.**") user.activate() repo.add(user) for i in range(3, (2 * test_domain.config["SNAPSHOT_THRESHOLD"]) + 2): with UnitOfWork(): user = repo.get(identifier) user.change_name(f"John Doe {i}") repo.add(user) snapshot = test_domain.event_store.store._read_last_message( f"user:snapshot-{identifier}") assert snapshot is not None assert User(**snapshot["data"]) == user assert snapshot["data"]["name"] == "John Doe 20"
def test_that_uow_throws_exception_on_commit_or_rollback_without_being_started( self, test_domain): uow = UnitOfWork() with pytest.raises(InvalidOperationError): uow.commit() with pytest.raises(InvalidOperationError): uow.rollback()
def test_expected_version_error_on_version_mismatch(self, test_domain): identifier = str(uuid4()) with UnitOfWork(): repo = test_domain.repository_for(Person) person = Person(id=identifier, first_name="John", last_name="Doe") repo.add(person) person_dup1 = repo.get(identifier) person_dup2 = repo.get(identifier) with UnitOfWork(): person_dup1.first_name = "Jane" repo.add(person_dup1) with pytest.raises(ExpectedVersionError) as exc: with UnitOfWork(): person_dup2.first_name = "Baby" repo.add(person_dup2) assert exc.value.args[0] == ( f"Wrong expected version: {person_dup2._version} " f"(Aggregate: Person({identifier}), Version: {person_dup2._version+1})" )
def test_that_an_entity_can_be_added_within_uow(self, test_domain, persisted_post): repo = test_domain.repository_for(Post) with UnitOfWork(): comment = Comment(content="So La Ti Do") persisted_post.add_comments(comment) repo = test_domain.repository_for(Post) repo.add(persisted_post) # FIXME Refactor `outside_uow` to be a global thread variable # post_dao = test_domain.repository_for(Post)._dao # assert len(post_dao.outside_uow().get(persisted_post.id).comments) == 0 post = repo.get(persisted_post.id) assert len(post.comments) == 1 assert post.comments[0].content == "So La Ti Do"
def test_new_objects_are_committed_as_part_of_one_transaction( self, test_domain): # Add a Person the database repo = test_domain.repository_for(Person) repo.add(self.persisted_person(test_domain)) person_dao = test_domain.repository_for(Person)._dao # Initiate a UnitOfWork Session with UnitOfWork(): repo = test_domain.repository_for(Person) person2 = Person(first_name="Jane", last_name="Doe") repo.add(person2) # Test that the underlying database is untouched assert len(person_dao.outside_uow().query.all().items) == 1 assert len(person_dao.query.all().items) == 2
def test_updating_a_has_many_association(test_domain): test_domain.register(Post) test_domain.register(Comment) post_repo = test_domain.repository_for(Post) post = Post(content="bar") post.add_comments(Comment(content="foo", added_on=datetime.utcnow())) post_repo.add(post) with UnitOfWork(): refreshed_post = post_repo.get(post.id) assert refreshed_post is not None refreshed_comment = refreshed_post.comments[0] assert refreshed_comment is not None refreshed_comment.content = "baz" refreshed_post.add_comments(refreshed_comment) post_repo.add(refreshed_post)
def test_that_an_entity_can_be_removed_within_uow(self, test_domain, persisted_post): comment = Comment(content="So La Ti Do") persisted_post.add_comments(comment) repo = test_domain.repository_for(Post) repo.add(persisted_post) with UnitOfWork(): comment = persisted_post.comments[0] persisted_post.remove_comments(comment) repo = test_domain.repository_for(Post) repo.add(persisted_post) # FIXME Refactor `outside_uow` to be a global thread variable # assert comment.id in uow.changes_to_be_committed['default']['REMOVED'] post = repo.get(persisted_post.id) assert len(post.comments) == 0
def test_updated_objects_are_committed_as_part_of_one_transaction( self, test_domain): # Add a Person the database repo = test_domain.repository_for(Person) person = Person(first_name="John", last_name="Doe") repo.add(person) person_dao = test_domain.repository_for(Person)._dao # Initiate a UnitOfWork Session with UnitOfWork(): repo = test_domain.repository_for(Person) persisted_person = repo.get(person.id) persisted_person.last_name = "Dane" repo.add(persisted_person) # Test that the underlying database is untouched assert person_dao.outside_uow().get(person.id).last_name == "Doe" assert person_dao.get(person.id).last_name == "Dane"
def test_uow_can_be_initiated_with_context_manager(self, test_domain): with UnitOfWork() as uow: assert uow is not None assert uow.in_progress is True