From ea3ef813962c6ed2360cafee90212e7b13b4c5d8 Mon Sep 17 00:00:00 2001 From: Evan <2869018789@qq.com> Date: Mon, 22 Jun 2026 13:53:51 +0800 Subject: [PATCH] refactor(tests): replace mock_logger with caplog in 5 service tests (#37468) (#37715) Co-authored-by: Asuka Minato Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .../services/test_human_input_service.py | 9 +-- .../services/test_summary_index_service.py | 61 +++++++++++-------- .../services/test_trigger_provider_service.py | 4 +- .../services/test_vector_service.py | 18 +++--- .../test_webhook_service_additional.py | 34 +++++------ 5 files changed, 67 insertions(+), 59 deletions(-) diff --git a/api/tests/unit_tests/services/test_human_input_service.py b/api/tests/unit_tests/services/test_human_input_service.py index 4c4abbbb8ec..d9d81d66566 100644 --- a/api/tests/unit_tests/services/test_human_input_service.py +++ b/api/tests/unit_tests/services/test_human_input_service.py @@ -1,4 +1,5 @@ import dataclasses +import logging from datetime import datetime, timedelta from unittest.mock import MagicMock @@ -672,7 +673,7 @@ def test_enqueue_resume_workflow_not_found(mocker: MockerFixture, mock_session_f assert "WorkflowRun not found" in str(excinfo.value) -def test_enqueue_resume_app_not_found(mocker: MockerFixture, mock_session_factory): +def test_enqueue_resume_app_not_found(mocker, mock_session_factory, caplog): session_factory, session = mock_session_factory service = HumanInputService(session_factory) @@ -687,10 +688,10 @@ def test_enqueue_resume_app_not_found(mocker: MockerFixture, mock_session_factor ) session.execute.return_value.scalar_one_or_none.return_value = None - logger_spy = mocker.patch("services.human_input_service.logger") - service.enqueue_resume("workflow-run-id") - logger_spy.error.assert_called_once() + with caplog.at_level(logging.ERROR, logger="services.human_input_service"): + service.enqueue_resume("workflow-run-id") + assert any(r.levelno >= logging.ERROR for r in caplog.records) def test_is_globally_expired_zero_timeout( diff --git a/api/tests/unit_tests/services/test_summary_index_service.py b/api/tests/unit_tests/services/test_summary_index_service.py index e17d4134ace..cef11c0038d 100644 --- a/api/tests/unit_tests/services/test_summary_index_service.py +++ b/api/tests/unit_tests/services/test_summary_index_service.py @@ -2,6 +2,7 @@ from __future__ import annotations +import logging import sys from dataclasses import dataclass from datetime import UTC, datetime @@ -532,7 +533,10 @@ def test_vectorize_summary_error_handler_tries_chunk_id_lookup_and_can_warn_not_ error_session.commit.assert_not_called() -def test_update_summary_record_error_warns_when_missing(monkeypatch: pytest.MonkeyPatch) -> None: +def test_update_summary_record_error_warns_when_missing( + monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, +) -> None: dataset = _dataset() segment = _segment() @@ -544,14 +548,15 @@ def test_update_summary_record_error_warns_when_missing(monkeypatch: pytest.Monk SimpleNamespace(create_session=MagicMock(return_value=_SessionContext(session))), ) - logger_mock = MagicMock() - monkeypatch.setattr(summary_module, "logger", logger_mock) - - SummaryIndexService.update_summary_record_error(segment, dataset, "err") - logger_mock.warning.assert_called_once() + with caplog.at_level(logging.WARNING, logger="services.summary_index_service"): + SummaryIndexService.update_summary_record_error(segment, dataset, "err") + assert any(r.levelno >= logging.WARNING for r in caplog.records) -def test_generate_and_vectorize_summary_creates_missing_record_and_logs_usage(monkeypatch: pytest.MonkeyPatch) -> None: +def test_generate_and_vectorize_summary_creates_missing_record_and_logs_usage( + monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, +) -> None: dataset = _dataset() segment = _segment() @@ -567,12 +572,10 @@ def test_generate_and_vectorize_summary_creates_missing_record_and_logs_usage(mo monkeypatch.setattr(SummaryIndexService, "generate_summary_for_segment", MagicMock(return_value=("sum", usage))) monkeypatch.setattr(SummaryIndexService, "vectorize_summary", MagicMock(return_value=None)) - logger_mock = MagicMock() - monkeypatch.setattr(summary_module, "logger", logger_mock) - - result = SummaryIndexService.generate_and_vectorize_summary(segment, dataset, {"enable": True}) - assert result.status in {SummaryStatus.GENERATING, SummaryStatus.COMPLETED} - logger_mock.info.assert_called() + with caplog.at_level(logging.INFO, logger="services.summary_index_service"): + result = SummaryIndexService.generate_and_vectorize_summary(segment, dataset, {"enable": True}) + assert result.status in {SummaryStatus.GENERATING, SummaryStatus.COMPLETED} + assert any(r.levelno >= logging.INFO for r in caplog.records) def test_generate_summaries_for_document_skip_conditions(monkeypatch: pytest.MonkeyPatch) -> None: @@ -759,6 +762,7 @@ def test_enable_summaries_for_segments_no_summaries_noop(monkeypatch: pytest.Mon def test_enable_summaries_for_segments_skips_segment_or_content_and_handles_vectorize_error( monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, ) -> None: dataset = _dataset() summary1 = _summary_record(summary_content="sum", node_id="n1") @@ -786,12 +790,11 @@ def test_enable_summaries_for_segments_skips_segment_or_content_and_handles_vect SimpleNamespace(create_session=MagicMock(return_value=_SessionContext(session))), ) - logger_mock = MagicMock() - monkeypatch.setattr(summary_module, "logger", logger_mock) monkeypatch.setattr(SummaryIndexService, "vectorize_summary", MagicMock(side_effect=RuntimeError("boom"))) - SummaryIndexService.enable_summaries_for_segments(dataset) - logger_mock.exception.assert_called_once() + with caplog.at_level(logging.ERROR, logger="services.summary_index_service"): + SummaryIndexService.enable_summaries_for_segments(dataset) + assert any(r.levelno >= logging.ERROR for r in caplog.records) session.commit.assert_called_once() @@ -859,7 +862,10 @@ def test_update_summary_for_segment_empty_content_deletes_existing(monkeypatch: session.commit.assert_called_once() -def test_update_summary_for_segment_empty_content_delete_vector_warns(monkeypatch: pytest.MonkeyPatch) -> None: +def test_update_summary_for_segment_empty_content_delete_vector_warns( + monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, +) -> None: dataset = _dataset() segment = _segment() record = _summary_record(summary_content="old", node_id="n1") @@ -875,11 +881,10 @@ def test_update_summary_for_segment_empty_content_delete_vector_warns(monkeypatc vector_instance = MagicMock() vector_instance.delete_by_ids.side_effect = RuntimeError("boom") monkeypatch.setattr(summary_module, "Vector", MagicMock(return_value=vector_instance)) - logger_mock = MagicMock() - monkeypatch.setattr(summary_module, "logger", logger_mock) - assert SummaryIndexService.update_summary_for_segment(segment, dataset, "") is None - logger_mock.warning.assert_called() + with caplog.at_level(logging.WARNING, logger="services.summary_index_service"): + assert SummaryIndexService.update_summary_for_segment(segment, dataset, "") is None + assert any(r.levelno >= logging.WARNING for r in caplog.records) def test_update_summary_for_segment_empty_content_no_record_noop(monkeypatch: pytest.MonkeyPatch) -> None: @@ -923,7 +928,10 @@ def test_update_summary_for_segment_updates_existing_and_vectorizes(monkeypatch: session.commit.assert_called() -def test_update_summary_for_segment_existing_vector_delete_warns(monkeypatch: pytest.MonkeyPatch) -> None: +def test_update_summary_for_segment_existing_vector_delete_warns( + monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, +) -> None: dataset = _dataset() segment = _segment() record = _summary_record(summary_content="old", node_id="n1") @@ -940,11 +948,10 @@ def test_update_summary_for_segment_existing_vector_delete_warns(monkeypatch: py vector_instance.delete_by_ids.side_effect = RuntimeError("boom") monkeypatch.setattr(summary_module, "Vector", MagicMock(return_value=vector_instance)) monkeypatch.setattr(SummaryIndexService, "vectorize_summary", MagicMock(return_value=None)) - logger_mock = MagicMock() - monkeypatch.setattr(summary_module, "logger", logger_mock) - SummaryIndexService.update_summary_for_segment(segment, dataset, "new") - logger_mock.warning.assert_called() + with caplog.at_level(logging.WARNING, logger="services.summary_index_service"): + SummaryIndexService.update_summary_for_segment(segment, dataset, "new") + assert any(r.levelno >= logging.WARNING for r in caplog.records) def test_update_summary_for_segment_existing_vectorize_failure_returns_error_record( diff --git a/api/tests/unit_tests/services/test_trigger_provider_service.py b/api/tests/unit_tests/services/test_trigger_provider_service.py index a47d946bab0..0a4452cf478 100644 --- a/api/tests/unit_tests/services/test_trigger_provider_service.py +++ b/api/tests/unit_tests/services/test_trigger_provider_service.py @@ -253,7 +253,7 @@ def test_add_trigger_subscription_should_raise_error_when_provider_limit_reached mock_session: MagicMock, provider_id: TriggerProviderID, provider_controller: MagicMock, - caplog, + caplog: pytest.LogCaptureFixture, ) -> None: # Arrange _patch_redis_lock(mocker) @@ -274,7 +274,7 @@ def test_add_trigger_subscription_should_raise_error_when_provider_limit_reached properties={}, credentials={}, ) - assert sum(1 for r in caplog.records if r.levelno >= logging.ERROR) == 1 + assert any(r.levelno >= logging.ERROR for r in caplog.records) def test_add_trigger_subscription_should_raise_error_when_name_exists( diff --git a/api/tests/unit_tests/services/test_vector_service.py b/api/tests/unit_tests/services/test_vector_service.py index e6cc59144b3..a5873870103 100644 --- a/api/tests/unit_tests/services/test_vector_service.py +++ b/api/tests/unit_tests/services/test_vector_service.py @@ -269,7 +269,8 @@ def test_create_segments_vector_parent_child_uses_default_embedding_model_when_p def test_create_segments_vector_parent_child_missing_document_logs_warning_and_continues( - monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture + monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, ) -> None: dataset = _make_dataset(doc_form=vector_service_module.IndexStructureType.PARENT_CHILD_INDEX) segment = _make_segment() @@ -290,7 +291,7 @@ def test_create_segments_vector_parent_child_missing_document_logs_warning_and_c VectorService.create_segments_vector( None, [segment], dataset, vector_service_module.IndexStructureType.PARENT_CHILD_INDEX ) - assert "Expected DatasetDocument record to exist, but none was found" in caplog.text + assert any(r.levelno >= logging.WARNING for r in caplog.records) index_processor.load.assert_not_called() @@ -614,7 +615,8 @@ def test_update_multimodel_vector_commits_when_no_upload_files_found(monkeypatch def test_update_multimodel_vector_adds_bindings_and_vectors_and_skips_missing_upload_files( - monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture + monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, ) -> None: dataset = _make_dataset(indexing_technique=IndexTechniqueType.HIGH_QUALITY, is_multimodal=True) segment = _make_segment(segment_id="seg-1", tenant_id="tenant-1", attachments=[{"id": "old-1"}]) @@ -631,8 +633,7 @@ def test_update_multimodel_vector_adds_bindings_and_vectors_and_skips_missing_up with caplog.at_level(logging.WARNING, logger="services.vector_service"): VectorService.update_multimodel_vector(segment=segment, attachment_ids=["file-1", "missing"], dataset=dataset) - - assert "Upload file not found for attachment_id" in caplog.text + assert any(r.levelno >= logging.WARNING for r in caplog.records) db_mock.session.add_all.assert_called_once() bindings = db_mock.session.add_all.call_args.args[0] assert len(bindings) == 1 @@ -671,7 +672,8 @@ def test_update_multimodel_vector_updates_bindings_without_multimodal_vector_ops def test_update_multimodel_vector_rolls_back_and_reraises_on_error( - monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture + monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, ) -> None: dataset = _make_dataset(indexing_technique=IndexTechniqueType.HIGH_QUALITY, is_multimodal=True) segment = _make_segment(segment_id="seg-1", tenant_id="tenant-1", attachments=[{"id": "old-1"}]) @@ -691,7 +693,5 @@ def test_update_multimodel_vector_rolls_back_and_reraises_on_error( with pytest.raises(RuntimeError, match="boom"): VectorService.update_multimodel_vector(segment=segment, attachment_ids=["file-1"], dataset=dataset) - exception_records = [r for r in caplog.records if r.levelname == "ERROR"] - assert len(exception_records) == 1 - assert "Failed to update multimodal vector for segment" in exception_records[0].getMessage() + assert any(r.levelno >= logging.ERROR for r in caplog.records) db_mock.session.rollback.assert_called_once() diff --git a/api/tests/unit_tests/services/test_webhook_service_additional.py b/api/tests/unit_tests/services/test_webhook_service_additional.py index 491dd948427..e3a8e282e9c 100644 --- a/api/tests/unit_tests/services/test_webhook_service_additional.py +++ b/api/tests/unit_tests/services/test_webhook_service_additional.py @@ -1,3 +1,4 @@ +import logging from types import SimpleNamespace from typing import Any from unittest.mock import MagicMock @@ -31,21 +32,21 @@ class TestWebhookServiceExtractionFallbacks: self, flask_app: Flask, monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, ) -> None: - warning_mock = MagicMock() - monkeypatch.setattr(service_module.logger, "warning", warning_mock) webhook_trigger = MagicMock() - with flask_app.test_request_context( - "/webhook", - method="POST", - headers={"Content-Type": "application/vnd.custom"}, - data="plain content", - ): - result = WebhookService.extract_webhook_data(webhook_trigger) + with caplog.at_level(logging.WARNING, logger="services.trigger.webhook_service"): + with flask_app.test_request_context( + "/webhook", + method="POST", + headers={"Content-Type": "application/vnd.custom"}, + data="plain content", + ): + result = WebhookService.extract_webhook_data(webhook_trigger) - assert result["body"] == {"raw": "plain content"} - warning_mock.assert_called_once() + assert result["body"] == {"raw": "plain content"} + assert any(r.levelno >= logging.WARNING for r in caplog.records) def test_extract_webhook_data_should_raise_for_request_too_large( self, @@ -171,14 +172,13 @@ class TestWebhookServiceValidationAndConversion: def test_validate_json_value_should_return_original_for_unmapped_supported_segment_type( self, monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, ) -> None: - warning_mock = MagicMock() - monkeypatch.setattr(service_module.logger, "warning", warning_mock) + with caplog.at_level(logging.WARNING, logger="services.trigger.webhook_service"): + result = WebhookService._validate_json_value("param", {"x": 1}, "unsupported-type") - result = WebhookService._validate_json_value("param", {"x": 1}, "unsupported-type") - - assert result == {"x": 1} - warning_mock.assert_called_once() + assert result == {"x": 1} + assert any(r.levelno >= logging.WARNING for r in caplog.records) def test_validate_and_convert_value_should_wrap_conversion_errors(self) -> None: with pytest.raises(ValueError, match="validation failed"):