""" 应用层异常单元测试 测试应用层异常类的创建、属性和行为。 """ import pytest from src.application.shared.exceptions import ( ApplicationException, ResourceNotFoundException, ValidationException, ) class TestApplicationException: """ApplicationException 单元测试""" def test_create_with_message_only(self): """测试仅使用消息创建异常""" # Arrange & Act exception = ApplicationException("Test error") # Assert assert exception.message == "Test error" assert exception.details == {} assert str(exception) == "Test error" def test_create_with_message_and_details(self): """测试使用消息和详细信息创建异常""" # Arrange details = {"key": "value", "code": 123} # Act exception = ApplicationException("Test error", details=details) # Assert assert exception.message == "Test error" assert exception.details == details assert "Test error" in str(exception) assert "Details:" in str(exception) def test_str_representation(self): """测试异常的字符串表示""" # Arrange exception = ApplicationException( "Error occurred", details={"reason": "Invalid input"} ) # Act result = str(exception) # Assert assert "Error occurred" in result assert "Details:" in result assert "reason" in result def test_repr_representation(self): """测试异常的详细表示""" # Arrange exception = ApplicationException( "Error occurred", details={"reason": "Invalid input"} ) # Act result = repr(exception) # Assert assert "ApplicationException" in result assert "message=" in result assert "details=" in result def test_exception_can_be_raised_and_caught(self): """测试异常可以被抛出和捕获""" # Arrange & Act & Assert with pytest.raises(ApplicationException) as exc_info: raise ApplicationException("Test error") assert exc_info.value.message == "Test error" def test_exception_inherits_from_exception(self): """测试异常继承自 Exception""" # Arrange exception = ApplicationException("Test error") # Act & Assert assert isinstance(exception, Exception) class TestResourceNotFoundException: """ResourceNotFoundException 单元测试""" def test_create_with_resource_type_and_id(self): """测试使用资源类型和 ID 创建异常""" # Arrange & Act exception = ResourceNotFoundException( resource_type="Document", resource_id="doc_123" ) # Assert assert exception.resource_type == "Document" assert exception.resource_id == "doc_123" assert "Document" in exception.message assert "doc_123" in exception.message assert "not found" in exception.message def test_details_include_resource_info(self): """测试详细信息包含资源信息""" # Arrange & Act exception = ResourceNotFoundException( resource_type="KnowledgeBase", resource_id="kb_456" ) # Assert assert exception.details["resource_type"] == "KnowledgeBase" assert exception.details["resource_id"] == "kb_456" def test_create_with_additional_details(self): """测试使用额外详细信息创建异常""" # Arrange additional_details = {"reason": "Database query returned no results"} # Act exception = ResourceNotFoundException( resource_type="Document", resource_id="doc_789", details=additional_details ) # Assert assert exception.details["resource_type"] == "Document" assert exception.details["resource_id"] == "doc_789" assert exception.details["reason"] == "Database query returned no results" def test_exception_message_format(self): """测试异常消息格式""" # Arrange & Act exception = ResourceNotFoundException( resource_type="ParsedDocument", resource_id="parsed_001" ) # Act message = exception.message # Assert assert message == "ParsedDocument with id 'parsed_001' not found" def test_exception_inherits_from_application_exception(self): """测试异常继承自 ApplicationException""" # Arrange exception = ResourceNotFoundException( resource_type="Document", resource_id="doc_123" ) # Act & Assert assert isinstance(exception, ApplicationException) assert isinstance(exception, Exception) class TestValidationException: """ValidationException 单元测试""" def test_create_with_message_only(self): """测试仅使用消息创建异常""" # Arrange & Act exception = ValidationException("Validation failed") # Assert assert exception.message == "Validation failed" assert exception.field is None assert exception.reason is None assert exception.details == {} def test_create_with_field_and_reason(self): """测试使用字段和原因创建异常""" # Arrange & Act exception = ValidationException( message="Invalid content", field="content", reason="Content cannot be empty" ) # Assert assert exception.message == "Invalid content" assert exception.field == "content" assert exception.reason == "Content cannot be empty" assert exception.details["field"] == "content" assert exception.details["reason"] == "Content cannot be empty" def test_create_with_field_only(self): """测试仅使用字段创建异常""" # Arrange & Act exception = ValidationException( message="Invalid input", field="email" ) # Assert assert exception.field == "email" assert exception.reason is None assert "field" in exception.details assert "reason" not in exception.details def test_create_with_reason_only(self): """测试仅使用原因创建异常""" # Arrange & Act exception = ValidationException( message="Invalid input", reason="Must be a positive number" ) # Assert assert exception.field is None assert exception.reason == "Must be a positive number" assert "field" not in exception.details assert "reason" in exception.details def test_create_with_additional_details(self): """测试使用额外详细信息创建异常""" # Arrange additional_details = { "min_length": 10, "max_length": 100, "actual_length": 5 } # Act exception = ValidationException( message="Invalid length", field="description", reason="Length out of range", details=additional_details ) # Assert assert exception.details["field"] == "description" assert exception.details["reason"] == "Length out of range" assert exception.details["min_length"] == 10 assert exception.details["max_length"] == 100 assert exception.details["actual_length"] == 5 def test_exception_inherits_from_application_exception(self): """测试异常继承自 ApplicationException""" # Arrange exception = ValidationException("Validation failed") # Act & Assert assert isinstance(exception, ApplicationException) assert isinstance(exception, Exception) def test_multiple_validation_errors(self): """测试多个验证错误""" # Arrange errors = [ {"field": "email", "reason": "Invalid format"}, {"field": "age", "reason": "Must be positive"} ] # Act exception = ValidationException( message="Multiple validation errors", details={"errors": errors} ) # Assert assert "errors" in exception.details assert len(exception.details["errors"]) == 2