""" 共享领域异常单元测试 测试领域异常类型的创建和行为。 """ import pytest from src.domain.shared.exceptions import ( BusinessRuleViolationException, DomainException, DomainValidationException, EntityNotFoundException, InvalidValueException, ) class TestDomainException: """DomainException 基类单元测试""" def test_create_domain_exception_with_message(self): """测试使用消息创建领域异常""" # Act exception = DomainException("Something went wrong") # Assert assert exception.message == "Something went wrong" assert exception.details == {} assert str(exception) == "Something went wrong" def test_create_domain_exception_with_message_and_details(self): """测试使用消息和详细信息创建领域异常""" # Arrange details = {"field": "name", "value": "invalid"} # Act exception = DomainException("Invalid input", details) # Assert assert exception.message == "Invalid input" assert exception.details == details assert "details:" in str(exception) def test_domain_exception_repr(self): """测试领域异常的详细表示""" # Arrange exception = DomainException("Test error", {"key": "value"}) # Act repr_str = repr(exception) # Assert assert "DomainException" in repr_str assert "Test error" in repr_str assert "key" in repr_str def test_domain_exception_can_be_raised(self): """测试领域异常可以被抛出和捕获""" # Act & Assert with pytest.raises(DomainException) as exc_info: raise DomainException("Test error") assert exc_info.value.message == "Test error" class TestInvalidValueException: """InvalidValueException 单元测试""" def test_create_invalid_value_exception(self): """测试创建无效值异常""" # Act exception = InvalidValueException( field_name="email", invalid_value="invalid-email", reason="Email format is invalid" ) # Assert assert exception.field_name == "email" assert exception.invalid_value == "invalid-email" assert exception.reason == "Email format is invalid" assert "email" in exception.message assert "Email format is invalid" in exception.message def test_invalid_value_exception_details(self): """测试无效值异常的详细信息""" # Act exception = InvalidValueException( field_name="age", invalid_value=-5, reason="Age must be positive" ) # Assert assert exception.details["field_name"] == "age" assert exception.details["invalid_value"] == "-5" assert exception.details["reason"] == "Age must be positive" def test_invalid_value_exception_with_additional_details(self): """测试带额外详细信息的无效值异常""" # Arrange additional_details = {"min_value": 0, "max_value": 150} # Act exception = InvalidValueException( field_name="age", invalid_value=-5, reason="Age out of range", details=additional_details ) # Assert assert exception.details["min_value"] == 0 assert exception.details["max_value"] == 150 assert exception.details["field_name"] == "age" def test_invalid_value_exception_can_be_raised(self): """测试无效值异常可以被抛出和捕获""" # Act & Assert with pytest.raises(InvalidValueException) as exc_info: raise InvalidValueException( field_name="test", invalid_value="bad", reason="Test reason" ) assert exc_info.value.field_name == "test" class TestBusinessRuleViolationException: """BusinessRuleViolationException 单元测试""" def test_create_business_rule_violation_exception(self): """测试创建业务规则违反异常""" # Act exception = BusinessRuleViolationException( rule_name="DocumentPublishRule", violation_reason="Cannot delete a published document" ) # Assert assert exception.rule_name == "DocumentPublishRule" assert exception.violation_reason == "Cannot delete a published document" assert "DocumentPublishRule" in exception.message assert "Cannot delete a published document" in exception.message def test_business_rule_violation_exception_details(self): """测试业务规则违反异常的详细信息""" # Act exception = BusinessRuleViolationException( rule_name="QuotaLimitRule", violation_reason="User has exceeded document quota" ) # Assert assert exception.details["rule_name"] == "QuotaLimitRule" assert exception.details["violation_reason"] == "User has exceeded document quota" def test_business_rule_violation_exception_with_additional_details(self): """测试带额外详细信息的业务规则违反异常""" # Arrange additional_details = { "document_id": "doc_123", "status": "published", "user_id": "user_456" } # Act exception = BusinessRuleViolationException( rule_name="DocumentDeletionRule", violation_reason="Published documents cannot be deleted", details=additional_details ) # Assert assert exception.details["document_id"] == "doc_123" assert exception.details["status"] == "published" assert exception.details["user_id"] == "user_456" def test_business_rule_violation_exception_can_be_raised(self): """测试业务规则违反异常可以被抛出和捕获""" # Act & Assert with pytest.raises(BusinessRuleViolationException) as exc_info: raise BusinessRuleViolationException( rule_name="TestRule", violation_reason="Test violation" ) assert exc_info.value.rule_name == "TestRule" class TestEntityNotFoundException: """EntityNotFoundException 单元测试""" def test_create_entity_not_found_exception(self): """测试创建实体未找到异常""" # Act exception = EntityNotFoundException( entity_type="Document", entity_id="doc_123" ) # Assert assert exception.entity_type == "Document" assert exception.entity_id == "doc_123" assert "Document" in exception.message assert "doc_123" in exception.message assert "not found" in exception.message def test_entity_not_found_exception_details(self): """测试实体未找到异常的详细信息""" # Act exception = EntityNotFoundException( entity_type="KnowledgeBase", entity_id="kb_456" ) # Assert assert exception.details["entity_type"] == "KnowledgeBase" assert exception.details["entity_id"] == "kb_456" def test_entity_not_found_exception_with_additional_details(self): """测试带额外详细信息的实体未找到异常""" # Arrange additional_details = {"search_criteria": {"name": "test"}} # Act exception = EntityNotFoundException( entity_type="User", entity_id="user_789", details=additional_details ) # Assert assert exception.details["search_criteria"] == {"name": "test"} def test_entity_not_found_exception_can_be_raised(self): """测试实体未找到异常可以被抛出和捕获""" # Act & Assert with pytest.raises(EntityNotFoundException) as exc_info: raise EntityNotFoundException( entity_type="Test", entity_id="test_123" ) assert exc_info.value.entity_type == "Test" class TestDomainValidationException: """DomainValidationException 单元测试""" def test_create_domain_validation_exception(self): """测试创建领域验证异常""" # Arrange validation_errors = [ {"field": "name", "error": "Name is required"}, {"field": "email", "error": "Email format is invalid"} ] # Act exception = DomainValidationException(validation_errors) # Assert assert exception.validation_errors == validation_errors assert "2 error(s)" in exception.message def test_domain_validation_exception_details(self): """测试领域验证异常的详细信息""" # Arrange validation_errors = [ {"field": "age", "error": "Age must be positive"} ] # Act exception = DomainValidationException(validation_errors) # Assert assert exception.details["validation_errors"] == validation_errors assert exception.details["error_count"] == 1 def test_domain_validation_exception_with_multiple_errors(self): """测试包含多个错误的领域验证异常""" # Arrange validation_errors = [ {"field": "name", "error": "Name is required"}, {"field": "email", "error": "Email is required"}, {"field": "age", "error": "Age must be positive"} ] # Act exception = DomainValidationException(validation_errors) # Assert assert len(exception.validation_errors) == 3 assert exception.details["error_count"] == 3 assert "3 error(s)" in exception.message def test_domain_validation_exception_with_additional_details(self): """测试带额外详细信息的领域验证异常""" # Arrange validation_errors = [{"field": "test", "error": "Test error"}] additional_details = {"context": "user_registration"} # Act exception = DomainValidationException( validation_errors, details=additional_details ) # Assert assert exception.details["context"] == "user_registration" def test_domain_validation_exception_can_be_raised(self): """测试领域验证异常可以被抛出和捕获""" # Arrange validation_errors = [{"field": "test", "error": "Test error"}] # Act & Assert with pytest.raises(DomainValidationException) as exc_info: raise DomainValidationException(validation_errors) assert len(exc_info.value.validation_errors) == 1 class TestExceptionHierarchy: """测试异常层次结构""" def test_all_domain_exceptions_inherit_from_domain_exception(self): """测试所有领域异常都继承自 DomainException""" # Assert assert issubclass(InvalidValueException, DomainException) assert issubclass(BusinessRuleViolationException, DomainException) assert issubclass(EntityNotFoundException, DomainException) assert issubclass(DomainValidationException, DomainException) def test_can_catch_all_domain_exceptions_with_base_class(self): """测试可以使用基类捕获所有领域异常""" # Test InvalidValueException with pytest.raises(DomainException): raise InvalidValueException("field", "value", "reason") # Test BusinessRuleViolationException with pytest.raises(DomainException): raise BusinessRuleViolationException("rule", "reason") # Test EntityNotFoundException with pytest.raises(DomainException): raise EntityNotFoundException("Entity", "id") # Test DomainValidationException with pytest.raises(DomainException): raise DomainValidationException([{"field": "test", "error": "error"}])