diff --git a/api/tests/unit_tests/core/repositories/test_factory.py b/api/tests/unit_tests/core/repositories/test_factory.py index 1b47cb64a70..a7f8eba0b87 100644 --- a/api/tests/unit_tests/core/repositories/test_factory.py +++ b/api/tests/unit_tests/core/repositories/test_factory.py @@ -9,7 +9,7 @@ from unittest.mock import MagicMock, patch import pytest from sqlalchemy.engine import Engine -from sqlalchemy.orm import sessionmaker +from sqlalchemy.orm import Session, sessionmaker from core.repositories.factory import ( DifyCoreRepositoryFactory, @@ -25,6 +25,15 @@ from models.workflow import WorkflowNodeExecutionTriggeredFrom RESOURCE_TENANT_ID = "resource-tenant-id" +@pytest.fixture +def sqlite_session_factory(sqlite_engine: Engine) -> sessionmaker[Session]: + """Return a real session factory bound to the test's isolated SQLite engine.""" + factory = sessionmaker(bind=sqlite_engine, expire_on_commit=False) + with factory() as session: + assert session.get_bind() is sqlite_engine + return factory + + class TestRepositoryFactory: """Test cases for RepositoryFactory.""" @@ -54,13 +63,12 @@ class TestRepositoryFactory: assert "doesn't look like a module path" in str(exc_info.value) @patch("core.repositories.factory.dify_config") - def test_create_workflow_execution_repository_success(self, mock_config): + def test_create_workflow_execution_repository_success(self, mock_config, sqlite_session_factory): """Test successful WorkflowExecutionRepository creation.""" # Setup mock configuration mock_config.CORE_WORKFLOW_EXECUTION_REPOSITORY = "unittest.mock.MagicMock" - # Create mock dependencies - mock_session_factory = MagicMock(spec=sessionmaker) + # Create non-database dependencies mock_user = MagicMock(spec=Account) app_id = "test-app-id" triggered_from = WorkflowRunTriggeredFrom.APP_RUN @@ -73,7 +81,7 @@ class TestRepositoryFactory: # Mock import_string with patch("core.repositories.factory.import_string", return_value=mock_repository_class, autospec=True): result = DifyCoreRepositoryFactory.create_workflow_execution_repository( - session_factory=mock_session_factory, + session_factory=sqlite_session_factory, tenant_id=RESOURCE_TENANT_ID, user=mock_user, app_id=app_id, @@ -82,7 +90,7 @@ class TestRepositoryFactory: # Verify the repository was created with correct parameters mock_repository_class.assert_called_once_with( - session_factory=mock_session_factory, + session_factory=sqlite_session_factory, tenant_id=RESOURCE_TENANT_ID, user=mock_user, app_id=app_id, @@ -91,17 +99,16 @@ class TestRepositoryFactory: assert result is mock_repository_instance @patch("core.repositories.factory.dify_config") - def test_create_workflow_execution_repository_import_error(self, mock_config): + def test_create_workflow_execution_repository_import_error(self, mock_config, sqlite_session_factory): """Test WorkflowExecutionRepository creation with import error.""" # Setup mock configuration with invalid class path mock_config.CORE_WORKFLOW_EXECUTION_REPOSITORY = "invalid.module.InvalidClass" - mock_session_factory = MagicMock(spec=sessionmaker) mock_user = MagicMock(spec=Account) with pytest.raises(RepositoryImportError) as exc_info: DifyCoreRepositoryFactory.create_workflow_execution_repository( - session_factory=mock_session_factory, + session_factory=sqlite_session_factory, tenant_id=RESOURCE_TENANT_ID, user=mock_user, app_id="test-app-id", @@ -110,12 +117,11 @@ class TestRepositoryFactory: assert "Failed to create WorkflowExecutionRepository" in str(exc_info.value) @patch("core.repositories.factory.dify_config") - def test_create_workflow_execution_repository_instantiation_error(self, mock_config): + def test_create_workflow_execution_repository_instantiation_error(self, mock_config, sqlite_session_factory): """Test WorkflowExecutionRepository creation with instantiation error.""" # Setup mock configuration mock_config.CORE_WORKFLOW_EXECUTION_REPOSITORY = "unittest.mock.MagicMock" - mock_session_factory = MagicMock(spec=sessionmaker) mock_user = MagicMock(spec=Account) # Create a mock repository class that raises exception on instantiation @@ -126,7 +132,7 @@ class TestRepositoryFactory: with patch("core.repositories.factory.import_string", return_value=mock_repository_class, autospec=True): with pytest.raises(RepositoryImportError) as exc_info: DifyCoreRepositoryFactory.create_workflow_execution_repository( - session_factory=mock_session_factory, + session_factory=sqlite_session_factory, tenant_id=RESOURCE_TENANT_ID, user=mock_user, app_id="test-app-id", @@ -135,13 +141,12 @@ class TestRepositoryFactory: assert "Failed to create WorkflowExecutionRepository" in str(exc_info.value) @patch("core.repositories.factory.dify_config") - def test_create_workflow_node_execution_repository_success(self, mock_config): + def test_create_workflow_node_execution_repository_success(self, mock_config, sqlite_session_factory): """Test successful WorkflowNodeExecutionRepository creation.""" # Setup mock configuration mock_config.CORE_WORKFLOW_NODE_EXECUTION_REPOSITORY = "unittest.mock.MagicMock" - # Create mock dependencies - mock_session_factory = MagicMock(spec=sessionmaker) + # Create non-database dependencies mock_user = MagicMock(spec=EndUser) app_id = "test-app-id" triggered_from = WorkflowNodeExecutionTriggeredFrom.SINGLE_STEP @@ -154,7 +159,7 @@ class TestRepositoryFactory: # Mock import_string with patch("core.repositories.factory.import_string", return_value=mock_repository_class, autospec=True): result = DifyCoreRepositoryFactory.create_workflow_node_execution_repository( - session_factory=mock_session_factory, + session_factory=sqlite_session_factory, tenant_id=RESOURCE_TENANT_ID, user=mock_user, app_id=app_id, @@ -163,7 +168,7 @@ class TestRepositoryFactory: # Verify the repository was created with correct parameters mock_repository_class.assert_called_once_with( - session_factory=mock_session_factory, + session_factory=sqlite_session_factory, tenant_id=RESOURCE_TENANT_ID, user=mock_user, app_id=app_id, @@ -172,17 +177,16 @@ class TestRepositoryFactory: assert result is mock_repository_instance @patch("core.repositories.factory.dify_config") - def test_create_workflow_node_execution_repository_import_error(self, mock_config): + def test_create_workflow_node_execution_repository_import_error(self, mock_config, sqlite_session_factory): """Test WorkflowNodeExecutionRepository creation with import error.""" # Setup mock configuration with invalid class path mock_config.CORE_WORKFLOW_NODE_EXECUTION_REPOSITORY = "invalid.module.InvalidClass" - mock_session_factory = MagicMock(spec=sessionmaker) mock_user = MagicMock(spec=EndUser) with pytest.raises(RepositoryImportError) as exc_info: DifyCoreRepositoryFactory.create_workflow_node_execution_repository( - session_factory=mock_session_factory, + session_factory=sqlite_session_factory, tenant_id=RESOURCE_TENANT_ID, user=mock_user, app_id="test-app-id", @@ -191,12 +195,11 @@ class TestRepositoryFactory: assert "Failed to create WorkflowNodeExecutionRepository" in str(exc_info.value) @patch("core.repositories.factory.dify_config") - def test_create_workflow_node_execution_repository_instantiation_error(self, mock_config): + def test_create_workflow_node_execution_repository_instantiation_error(self, mock_config, sqlite_session_factory): """Test WorkflowNodeExecutionRepository creation with instantiation error.""" # Setup mock configuration mock_config.CORE_WORKFLOW_NODE_EXECUTION_REPOSITORY = "unittest.mock.MagicMock" - mock_session_factory = MagicMock(spec=sessionmaker) mock_user = MagicMock(spec=EndUser) # Create a mock repository class that raises exception on instantiation @@ -207,7 +210,7 @@ class TestRepositoryFactory: with patch("core.repositories.factory.import_string", return_value=mock_repository_class, autospec=True): with pytest.raises(RepositoryImportError) as exc_info: DifyCoreRepositoryFactory.create_workflow_node_execution_repository( - session_factory=mock_session_factory, + session_factory=sqlite_session_factory, tenant_id=RESOURCE_TENANT_ID, user=mock_user, app_id="test-app-id", @@ -222,13 +225,12 @@ class TestRepositoryFactory: assert str(error) == error_message @patch("core.repositories.factory.dify_config") - def test_create_with_engine_instead_of_sessionmaker(self, mock_config): + def test_create_with_engine_instead_of_sessionmaker(self, mock_config, sqlite_engine: Engine): """Test repository creation with Engine instead of sessionmaker.""" # Setup mock configuration mock_config.CORE_WORKFLOW_EXECUTION_REPOSITORY = "unittest.mock.MagicMock" - # Create mock dependencies using Engine instead of sessionmaker - mock_engine = MagicMock(spec=Engine) + # Pass the real Engine directly instead of wrapping it in sessionmaker mock_user = MagicMock(spec=Account) app_id = "test-app-id" triggered_from = WorkflowRunTriggeredFrom.APP_RUN @@ -241,7 +243,7 @@ class TestRepositoryFactory: # Mock import_string with patch("core.repositories.factory.import_string", return_value=mock_repository_class, autospec=True): result = DifyCoreRepositoryFactory.create_workflow_execution_repository( - session_factory=mock_engine, # Using Engine instead of sessionmaker + session_factory=sqlite_engine, tenant_id=RESOURCE_TENANT_ID, user=mock_user, app_id=app_id, @@ -250,7 +252,7 @@ class TestRepositoryFactory: # Verify the repository was created with correct parameters mock_repository_class.assert_called_once_with( - session_factory=mock_engine, + session_factory=sqlite_engine, tenant_id=RESOURCE_TENANT_ID, user=mock_user, app_id=app_id,