#[cfg(test)] mod rag_grounding_tests { use crate::infrastructure::gemini_service::{ GeminiService, GeminiConfig, RagGroundingRequest, RagGroundingConfig, RagGroundingResponse, GroundingMetadata, GroundingSource, }; /// 创建测试用的 GeminiService 实例 fn create_test_service() -> GeminiService { let config = GeminiConfig::default(); GeminiService::new(Some(config)).expect("Failed to create test service") } /// 创建测试用的 RAG Grounding 请求 fn create_test_request() -> RagGroundingRequest { RagGroundingRequest { user_input: "测试查询".to_string(), config: Some(RagGroundingConfig::default()), session_id: Some("test-session".to_string()), } } #[test] fn test_rag_grounding_config_default() { let config = RagGroundingConfig::default(); assert_eq!(config.project_id, "gen-lang-client-0413414134"); assert_eq!(config.location, "global"); assert_eq!(config.data_store_id, "default_data_store"); assert_eq!(config.model_id, "gemini-2.5-flash"); assert_eq!(config.temperature, 1.0); assert_eq!(config.max_output_tokens, 8192); assert!(config.system_prompt.is_none()); } #[test] fn test_rag_grounding_request_creation() { let request = create_test_request(); assert_eq!(request.user_input, "测试查询"); assert!(request.config.is_some()); assert_eq!(request.session_id, Some("test-session".to_string())); } #[test] fn test_rag_grounding_request_serialization() { let request = create_test_request(); // 测试序列化 let serialized = serde_json::to_string(&request).expect("Failed to serialize request"); assert!(serialized.contains("测试查询")); assert!(serialized.contains("test-session")); // 测试反序列化 let deserialized: RagGroundingRequest = serde_json::from_str(&serialized) .expect("Failed to deserialize request"); assert_eq!(deserialized.user_input, request.user_input); assert_eq!(deserialized.session_id, request.session_id); } #[test] fn test_rag_grounding_response_creation() { let response = RagGroundingResponse { answer: "测试回答".to_string(), grounding_metadata: Some(GroundingMetadata { sources: vec![GroundingSource { title: "测试来源".to_string(), uri: Some("https://example.com".to_string()), snippet: "测试片段".to_string(), relevance_score: Some(0.95), }], search_queries: vec!["测试查询".to_string()], }), response_time_ms: 1500, model_used: "gemini-2.5-flash".to_string(), }; assert_eq!(response.answer, "测试回答"); assert!(response.grounding_metadata.is_some()); assert_eq!(response.response_time_ms, 1500); assert_eq!(response.model_used, "gemini-2.5-flash"); let metadata = response.grounding_metadata.unwrap(); assert_eq!(metadata.sources.len(), 1); assert_eq!(metadata.search_queries.len(), 1); let source = &metadata.sources[0]; assert_eq!(source.title, "测试来源"); assert_eq!(source.uri, Some("https://example.com".to_string())); assert_eq!(source.snippet, "测试片段"); assert_eq!(source.relevance_score, Some(0.95)); } #[test] fn test_grounding_metadata_empty() { let metadata = GroundingMetadata { sources: vec![], search_queries: vec![], }; assert!(metadata.sources.is_empty()); assert!(metadata.search_queries.is_empty()); } #[test] fn test_grounding_source_without_optional_fields() { let source = GroundingSource { title: "测试来源".to_string(), uri: None, snippet: "测试片段".to_string(), relevance_score: None, }; assert_eq!(source.title, "测试来源"); assert!(source.uri.is_none()); assert_eq!(source.snippet, "测试片段"); assert!(source.relevance_score.is_none()); } #[test] fn test_rag_grounding_config_with_system_prompt() { let mut config = RagGroundingConfig::default(); config.system_prompt = Some("你是一个专业的助手".to_string()); assert!(config.system_prompt.is_some()); assert_eq!(config.system_prompt.unwrap(), "你是一个专业的助手"); } #[test] fn test_rag_grounding_config_custom_values() { let config = RagGroundingConfig { project_id: "custom-project".to_string(), location: "us-central1".to_string(), data_store_id: "custom-datastore".to_string(), model_id: "gemini-pro".to_string(), temperature: 0.5, max_output_tokens: 4096, system_prompt: Some("自定义系统提示".to_string()), }; assert_eq!(config.project_id, "custom-project"); assert_eq!(config.location, "us-central1"); assert_eq!(config.data_store_id, "custom-datastore"); assert_eq!(config.model_id, "gemini-pro"); assert_eq!(config.temperature, 0.5); assert_eq!(config.max_output_tokens, 4096); assert_eq!(config.system_prompt, Some("自定义系统提示".to_string())); } #[test] fn test_gemini_service_creation() { let service = create_test_service(); // 基本的服务创建测试,确保没有panic assert!(true); // 如果能到这里说明服务创建成功 } /// 测试 JSON 响应解析 #[test] fn test_parse_rag_grounding_response_json() { let service = create_test_service(); // 模拟一个典型的 Gemini API 响应 let mock_response = r#"{ "candidates": [{ "content": { "parts": [{ "text": "这是一个测试回答" }] }, "groundingMetadata": { "groundingSources": [{ "title": "测试文档", "uri": "https://example.com/doc", "snippet": "这是一个测试片段", "relevanceScore": 0.85 }], "searchQueries": ["测试查询"] } }] }"#; let result = service.parse_rag_grounding_response(mock_response); assert!(result.is_ok()); let response = result.unwrap(); assert_eq!(response.answer, "这是一个测试回答"); assert!(response.grounding_metadata.is_some()); let metadata = response.grounding_metadata.unwrap(); assert_eq!(metadata.sources.len(), 1); assert_eq!(metadata.search_queries.len(), 1); let source = &metadata.sources[0]; assert_eq!(source.title, "测试文档"); assert_eq!(source.uri, Some("https://example.com/doc".to_string())); assert_eq!(source.snippet, "这是一个测试片段"); assert_eq!(source.relevance_score, Some(0.85)); } /// 测试无效 JSON 响应处理 #[test] fn test_parse_invalid_json_response() { let service = create_test_service(); let invalid_json = "这不是有效的JSON"; let result = service.parse_rag_grounding_response(invalid_json); assert!(result.is_err()); } /// 测试缺少必要字段的响应 #[test] fn test_parse_incomplete_response() { let service = create_test_service(); let incomplete_response = r#"{ "candidates": [] }"#; let result = service.parse_rag_grounding_response(incomplete_response); assert!(result.is_ok()); let response = result.unwrap(); assert_eq!(response.answer, "无法解析响应内容"); assert!(response.grounding_metadata.is_none()); } }