| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- """
- 测试 approve_order 功能
- 测试场景:
- 1. 验证 extract_output_domain_and_logic 方法能正确提取输出域和处理逻辑
- 2. 验证 generate_order_resources 方法能正确创建资源
- 3. 验证 approve_order 完整流程
- """
- import json
- from unittest.mock import MagicMock, patch
- import pytest
- class TestExtractOutputDomainAndLogic:
- """测试 extract_output_domain_and_logic 方法"""
- @patch("app.core.data_service.data_product_service.current_app")
- @patch("app.core.data_service.data_product_service.OpenAI")
- def test_extract_success(self, mock_openai, mock_app):
- """测试成功提取输出域和处理逻辑"""
- from app.core.data_service.data_product_service import DataOrderService
- # 模拟配置
- mock_app.config.get.side_effect = lambda key: {
- "LLM_API_KEY": "test-key",
- "LLM_BASE_URL": "http://test-url",
- "LLM_MODEL_NAME": "test-model",
- }.get(key)
- # 模拟 LLM 响应
- mock_response = MagicMock()
- mock_response.choices = [MagicMock()]
- mock_response.choices[0].message.content = json.dumps(
- {
- "output_domain": {
- "name_zh": "会员消费分析报表",
- "name_en": "member_consumption_analysis",
- "describe": "汇总会员消费数据的分析报表",
- },
- "processing_logic": "1. 从会员表提取会员ID、姓名;2. 从消费记录表提取消费金额;3. 按会员汇总消费总额",
- }
- )
- mock_openai.return_value.chat.completions.create.return_value = mock_response
- # 执行测试
- result = DataOrderService.extract_output_domain_and_logic(
- description="我需要一个会员消费分析报表,统计每个会员的消费总额",
- input_domains=[{"name_zh": "会员表"}, {"name_zh": "消费记录表"}],
- )
- # 验证结果
- assert "output_domain" in result
- assert result["output_domain"]["name_zh"] == "会员消费分析报表"
- assert result["output_domain"]["name_en"] == "member_consumption_analysis"
- assert "processing_logic" in result
- assert "消费" in result["processing_logic"]
- @patch("app.core.data_service.data_product_service.current_app")
- @patch("app.core.data_service.data_product_service.OpenAI")
- def test_extract_with_markdown_response(self, mock_openai, mock_app):
- """测试 LLM 返回带 markdown 代码块的响应"""
- from app.core.data_service.data_product_service import DataOrderService
- mock_app.config.get.side_effect = lambda key: {
- "LLM_API_KEY": "test-key",
- "LLM_BASE_URL": "http://test-url",
- "LLM_MODEL_NAME": "test-model",
- }.get(key)
- # 模拟带 markdown 代码块的响应
- mock_response = MagicMock()
- mock_response.choices = [MagicMock()]
- mock_response.choices[0].message.content = """```json
- {
- "output_domain": {
- "name_zh": "销售报表",
- "name_en": "sales_report",
- "describe": "销售数据汇总"
- },
- "processing_logic": "汇总销售数据"
- }
- ```"""
- mock_openai.return_value.chat.completions.create.return_value = mock_response
- result = DataOrderService.extract_output_domain_and_logic(
- description="生成销售报表"
- )
- assert result["output_domain"]["name_zh"] == "销售报表"
- @patch("app.core.data_service.data_product_service.current_app")
- @patch("app.core.data_service.data_product_service.OpenAI")
- def test_extract_fallback_on_error(self, mock_openai, mock_app):
- """测试 LLM 调用失败时的回退逻辑"""
- from app.core.data_service.data_product_service import DataOrderService
- mock_app.config.get.side_effect = lambda key: {
- "LLM_API_KEY": "test-key",
- "LLM_BASE_URL": "http://test-url",
- "LLM_MODEL_NAME": "test-model",
- }.get(key)
- # 模拟 LLM 调用异常
- mock_openai.return_value.chat.completions.create.side_effect = Exception(
- "LLM 服务不可用"
- )
- result = DataOrderService.extract_output_domain_and_logic(
- description="测试描述内容"
- )
- # 验证回退到默认值
- assert result["output_domain"]["name_zh"] == "数据产品"
- assert result["output_domain"]["name_en"] == "data_product"
- assert result["processing_logic"] == "测试描述内容"
- assert "error" in result
- class TestGenerateOrderResources:
- """测试 generate_order_resources 方法"""
- @patch("app.core.data_service.data_product_service.db")
- @patch("app.core.data_service.data_product_service.neo4j_driver")
- @patch.object(
- __import__(
- "app.core.data_service.data_product_service", fromlist=["DataOrderService"]
- ).DataOrderService,
- "extract_output_domain_and_logic",
- )
- def test_generate_resources_creates_all_components(
- self, mock_extract, mock_neo4j, mock_db
- ):
- """测试 generate_order_resources 创建所有必要的组件"""
- from app.core.data_service.data_product_service import DataOrderService
- from app.models.data_product import DataOrder
- # 模拟 LLM 提取结果
- mock_extract.return_value = {
- "output_domain": {
- "name_zh": "测试数据产品",
- "name_en": "test_data_product",
- "describe": "测试描述",
- },
- "processing_logic": "测试处理逻辑",
- }
- # 模拟订单对象
- mock_order = MagicMock(spec=DataOrder)
- mock_order.id = 1
- mock_order.order_no = "DO20240101001"
- mock_order.title = "测试订单"
- mock_order.description = "测试描述"
- mock_order.extraction_purpose = "测试用途"
- mock_order.extracted_fields = ["字段1", "字段2"]
- mock_order.graph_analysis = {
- "matched_domains": [
- {"id": 100, "name_zh": "源表1"},
- {"id": 101, "name_zh": "源表2"},
- ]
- }
- # 模拟 Neo4j session
- mock_session = MagicMock()
- mock_neo4j.get_session.return_value.__enter__ = MagicMock(
- return_value=mock_session
- )
- mock_neo4j.get_session.return_value.__exit__ = MagicMock(return_value=False)
- # 模拟创建 BusinessDomain 返回 ID
- mock_bd_result = MagicMock()
- mock_bd_result.__getitem__ = lambda self, key: 200 if key == "bd_id" else None
- mock_session.run.return_value.single.side_effect = [
- mock_bd_result, # 创建 BusinessDomain
- MagicMock(
- __getitem__=lambda self, key: 300 if key == "df_id" else None
- ), # 创建 DataFlow
- ]
- # 模拟 task_list 插入
- mock_db.session.execute.return_value.fetchone.return_value = (1,)
- # 执行测试
- result = DataOrderService.generate_order_resources(mock_order)
- # 验证结果
- assert result["target_business_domain_id"] == 200
- assert result["dataflow_id"] == 300
- assert result["input_domain_ids"] == [100, 101]
- assert "task_id" in result
- # 验证 LLM 提取被调用
- mock_extract.assert_called_once()
- class TestApproveOrderFlow:
- """测试完整的 approve_order 流程"""
- def test_approve_order_status_validation(self):
- """测试订单状态验证"""
- # 这个测试需要在实际环境中运行
- # 这里只提供测试框架
- pass
- def test_approve_order_success_flow(self):
- """测试审批成功的完整流程"""
- # 这个测试需要在实际环境中运行
- # 这里只提供测试框架
- pass
- if __name__ == "__main__":
- pytest.main([__file__, "-v"])
|