mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 23:47:41 +08:00
refactor: use injected eventmanager in chain instance methods
This commit is contained in:
@@ -108,13 +108,14 @@ def test_media_identity_conversion_rejects_invalid_pair_without_plugin_handler()
|
||||
media_source=MediaSource.Bangumi,
|
||||
media_id="0",
|
||||
) is None
|
||||
with patch("app.chain.media.eventmanager.send_event", return_value=None):
|
||||
assert MediaChain.convert_media_identity(
|
||||
chain,
|
||||
target_source=MediaSource.TheAudioDB,
|
||||
media_source=MediaSource.Bangumi,
|
||||
media_id="1",
|
||||
) is None
|
||||
# 无插件处理器:注入返回空的 eventmanager 桩
|
||||
chain.eventmanager = Mock(send_event=Mock(return_value=None))
|
||||
assert MediaChain.convert_media_identity(
|
||||
chain,
|
||||
target_source=MediaSource.TheAudioDB,
|
||||
media_source=MediaSource.Bangumi,
|
||||
media_id="1",
|
||||
) is None
|
||||
assert chain.tmdb_mtype is None
|
||||
assert chain.douban_mtype is None
|
||||
|
||||
@@ -129,13 +130,14 @@ def test_media_identity_conversion_dispatches_plugin_source() -> None:
|
||||
event_data.media_dict.update(result)
|
||||
return Mock(event_data=event_data)
|
||||
|
||||
with patch("app.chain.media.eventmanager.send_event", side_effect=handle_event):
|
||||
converted = MediaChain.convert_media_identity(
|
||||
chain,
|
||||
target_source=MediaSource.TMDB,
|
||||
media_source=MediaSource("acme.video"),
|
||||
media_id="custom-1",
|
||||
)
|
||||
# 事件经注入的 eventmanager 发送,测试桩直接提供实例依赖
|
||||
chain.eventmanager = Mock(send_event=Mock(side_effect=handle_event))
|
||||
converted = MediaChain.convert_media_identity(
|
||||
chain,
|
||||
target_source=MediaSource.TMDB,
|
||||
media_source=MediaSource("acme.video"),
|
||||
media_id="custom-1",
|
||||
)
|
||||
|
||||
assert converted == result
|
||||
|
||||
@@ -211,15 +213,13 @@ def test_async_media_identity_conversion_dispatches_plugin_source() -> None:
|
||||
event_data.media_dict.update(result)
|
||||
return Mock(event_data=event_data)
|
||||
|
||||
with patch(
|
||||
"app.chain.media.eventmanager.async_send_event",
|
||||
new=AsyncMock(side_effect=handle_event),
|
||||
):
|
||||
converted = asyncio.run(MediaChain.async_convert_media_identity(
|
||||
chain,
|
||||
target_source=MediaSource.Douban,
|
||||
media_source=MediaSource("acme.video"),
|
||||
media_id="custom-1",
|
||||
))
|
||||
# 事件经注入的 eventmanager 发送,测试桩直接提供实例依赖
|
||||
chain.eventmanager = Mock(async_send_event=AsyncMock(side_effect=handle_event))
|
||||
converted = asyncio.run(MediaChain.async_convert_media_identity(
|
||||
chain,
|
||||
target_source=MediaSource.Douban,
|
||||
media_source=MediaSource("acme.video"),
|
||||
media_id="custom-1",
|
||||
))
|
||||
|
||||
assert converted == result
|
||||
|
||||
@@ -558,6 +558,8 @@ def test_batch_download_rejects_complete_coverage_when_files_do_not_cover_target
|
||||
monkeypatch.setattr(download_module.eventmanager, "send_event", lambda *args, **kwargs: None)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
chain.download_torrent = MagicMock(return_value=(b"torrent-content", "", ["demo.mkv"]))
|
||||
chain.download_single = MagicMock(return_value="hash")
|
||||
|
||||
@@ -588,6 +590,8 @@ def test_batch_download_preserves_special_season_zero(monkeypatch):
|
||||
monkeypatch.setattr(download_module.eventmanager, "send_event", lambda *args, **kwargs: None)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
chain.download_torrent = MagicMock(return_value=(b"torrent-content", "", ["demo.mkv"]))
|
||||
chain.download_single = MagicMock(return_value="hash")
|
||||
|
||||
@@ -623,6 +627,8 @@ def test_batch_download_rejects_complete_coverage_when_only_missing_episodes_mat
|
||||
monkeypatch.setattr(download_module.eventmanager, "send_event", lambda *args, **kwargs: None)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
chain.download_torrent = MagicMock(return_value=(b"torrent-content", "", ["demo.mkv"]))
|
||||
chain.download_single = MagicMock(return_value="hash")
|
||||
|
||||
@@ -655,6 +661,8 @@ def test_batch_download_tries_next_episode_candidate_when_first_download_fails(m
|
||||
monkeypatch.setattr(download_module.eventmanager, "send_event", lambda *args, **kwargs: None)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
chain.download_single = MagicMock(side_effect=[None, "hash"])
|
||||
|
||||
first_context = _build_tv_context(episode_list=[1])
|
||||
@@ -692,6 +700,8 @@ def test_batch_download_does_not_download_duplicate_movie_after_success(monkeypa
|
||||
monkeypatch.setattr(download_module.eventmanager, "send_event", lambda *args, **kwargs: None)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
chain.download_single = MagicMock(return_value="hash")
|
||||
|
||||
first_context = SimpleNamespace(
|
||||
@@ -720,6 +730,8 @@ def test_batch_download_threads_custom_words_to_download_single(monkeypatch):
|
||||
monkeypatch.setattr(download_module.eventmanager, "send_event", lambda *args, **kwargs: None)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
chain.download_single = MagicMock(return_value="hash")
|
||||
|
||||
context = SimpleNamespace(
|
||||
@@ -744,6 +756,8 @@ def test_batch_download_applies_custom_words_to_torrent_file_episodes(monkeypatc
|
||||
monkeypatch.setattr(download_module.eventmanager, "send_event", lambda *args, **kwargs: None)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
chain.download_torrent = MagicMock(
|
||||
return_value=(b"torrent-content", "", ["A.Will.Eternal.S04E05.mkv"]),
|
||||
)
|
||||
@@ -807,6 +821,8 @@ def test_download_single_records_failure_cooldown_when_downloader_rejects(monkey
|
||||
monkeypatch.setattr(download_module.eventmanager, "send_event", lambda *args, **kwargs: None)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
error_msg = "添加种子任务失败:无法读取种子文件"
|
||||
chain.download = MagicMock(return_value=("qb", None, "Original", error_msg))
|
||||
chain.post_message = MagicMock()
|
||||
@@ -943,6 +959,8 @@ def test_batch_download_skips_failed_subscription_resource_and_tries_next(monkey
|
||||
)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
chain.download_single = MagicMock(return_value="hash")
|
||||
|
||||
downloads, lefts = chain.batch_download(
|
||||
@@ -965,6 +983,8 @@ def test_batch_download_accepts_complete_coverage_when_files_cover_target_range(
|
||||
monkeypatch.setattr(download_module.eventmanager, "send_event", lambda *args, **kwargs: None)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
chain.download_torrent = MagicMock(return_value=(b"torrent-content", "", ["demo.mkv"]))
|
||||
chain.download_single = MagicMock(return_value="hash")
|
||||
|
||||
@@ -997,6 +1017,8 @@ def test_batch_download_rejects_complete_coverage_when_files_have_same_count_but
|
||||
monkeypatch.setattr(download_module.eventmanager, "send_event", lambda *args, **kwargs: None)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
chain.download_torrent = MagicMock(return_value=(b"torrent-content", "", ["demo.mkv"]))
|
||||
chain.download_single = MagicMock(return_value="hash")
|
||||
|
||||
@@ -1029,6 +1051,8 @@ def test_batch_download_accepts_complete_coverage_when_title_episodes_cover_targ
|
||||
monkeypatch.setattr(download_module.eventmanager, "send_event", lambda *args, **kwargs: None)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
chain.download_torrent = MagicMock()
|
||||
chain.download_single = MagicMock(return_value="hash")
|
||||
|
||||
@@ -1062,6 +1086,8 @@ def test_batch_download_rejects_complete_coverage_when_title_episodes_are_partia
|
||||
monkeypatch.setattr(download_module.eventmanager, "send_event", lambda *args, **kwargs: None)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
chain.download_torrent = MagicMock()
|
||||
chain.download_single = MagicMock(return_value="hash")
|
||||
|
||||
@@ -1095,6 +1121,8 @@ def test_batch_download_complete_coverage_ignores_allowed_episode_narrowing(monk
|
||||
monkeypatch.setattr(download_module.eventmanager, "send_event", lambda *args, **kwargs: None)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
chain.download_torrent = MagicMock()
|
||||
chain.download_single = MagicMock(return_value="hash")
|
||||
|
||||
@@ -1129,6 +1157,8 @@ def test_batch_download_keeps_count_check_without_complete_coverage(monkeypatch)
|
||||
monkeypatch.setattr(download_module.eventmanager, "send_event", lambda *args, **kwargs: None)
|
||||
|
||||
chain = DownloadChain.__new__(DownloadChain)
|
||||
chain.eventmanager = MagicMock()
|
||||
chain.eventmanager.send_event.return_value = None
|
||||
chain.download_torrent = MagicMock(return_value=(b"torrent-content", "", ["demo.mkv"]))
|
||||
chain.download_single = MagicMock(return_value="hash")
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
与 ChainBase 媒体识别插件补充(MediaRecognize / MusicMediaRecognize 链式事件)。
|
||||
"""
|
||||
import asyncio
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
from unittest.mock import AsyncMock, MagicMock, Mock, patch
|
||||
|
||||
from app.chain import ChainBase
|
||||
from app.chain.media import MediaChain
|
||||
@@ -66,10 +66,12 @@ def test_music_recognize_help_sends_event_and_rematches(monkeypatch):
|
||||
"album": "叶惠美",
|
||||
"year": "2003",
|
||||
})
|
||||
with patch("app.chain.media.eventmanager") as em:
|
||||
em.check.return_value = True
|
||||
em.send_event.return_value = event
|
||||
result = chain.recognize_by_meta(meta, media_source="musicbrainz")
|
||||
# 事件经注入的 eventmanager 发送,直接替换实例依赖并保留断言能力
|
||||
em = MagicMock()
|
||||
em.check.return_value = True
|
||||
em.send_event.return_value = event
|
||||
monkeypatch.setattr(chain, "eventmanager", em)
|
||||
result = chain.recognize_by_meta(meta, media_source="musicbrainz")
|
||||
|
||||
assert result is remote
|
||||
assert em.check.call_args.args[0] == ChainEventType.MusicNameRecognize
|
||||
@@ -101,9 +103,10 @@ def test_music_recognize_keeps_fallback_without_plugin(monkeypatch):
|
||||
fallback = _fallback_music(title="未知曲目")
|
||||
monkeypatch.setattr(chain, "recognize_media", Mock(return_value=fallback))
|
||||
|
||||
with patch("app.chain.media.eventmanager") as em:
|
||||
em.check.return_value = False
|
||||
result = chain.recognize_by_meta(meta)
|
||||
em = MagicMock()
|
||||
em.check.return_value = False
|
||||
monkeypatch.setattr(chain, "eventmanager", em)
|
||||
result = chain.recognize_by_meta(meta)
|
||||
|
||||
assert result is fallback
|
||||
em.send_event.assert_not_called()
|
||||
@@ -122,10 +125,11 @@ def test_music_recognize_help_same_elements_keeps_fallback(monkeypatch):
|
||||
"name": "晴天",
|
||||
"artist": "周杰伦",
|
||||
})
|
||||
with patch("app.chain.media.eventmanager") as em:
|
||||
em.check.return_value = True
|
||||
em.send_event.return_value = event
|
||||
result = chain.recognize_by_meta(meta)
|
||||
em = MagicMock()
|
||||
em.check.return_value = True
|
||||
em.send_event.return_value = event
|
||||
monkeypatch.setattr(chain, "eventmanager", em)
|
||||
result = chain.recognize_by_meta(meta)
|
||||
|
||||
assert result is fallback
|
||||
assert recognize_mock.call_count == 1
|
||||
@@ -143,10 +147,11 @@ def test_music_recognize_help_keeps_fallback_when_rematch_fails(monkeypatch):
|
||||
"name": "另一个晴天",
|
||||
"artist": "未知艺术家",
|
||||
})
|
||||
with patch("app.chain.media.eventmanager") as em:
|
||||
em.check.return_value = True
|
||||
em.send_event.return_value = event
|
||||
result = chain.recognize_by_meta(meta)
|
||||
em = MagicMock()
|
||||
em.check.return_value = True
|
||||
em.send_event.return_value = event
|
||||
monkeypatch.setattr(chain, "eventmanager", em)
|
||||
result = chain.recognize_by_meta(meta)
|
||||
|
||||
assert result is fallback
|
||||
|
||||
@@ -169,10 +174,12 @@ def test_async_music_recognize_help(monkeypatch):
|
||||
"name": "晴天",
|
||||
"artist": "周杰伦",
|
||||
})
|
||||
with patch("app.chain.media.eventmanager") as em:
|
||||
em.check.return_value = True
|
||||
em.async_send_event = AsyncMock(return_value=event)
|
||||
result = asyncio.run(chain.async_recognize_by_meta(meta))
|
||||
# 事件经注入的 eventmanager 发送,直接替换实例依赖并保留断言能力
|
||||
em = MagicMock()
|
||||
em.check.return_value = True
|
||||
em.async_send_event = AsyncMock(return_value=event)
|
||||
monkeypatch.setattr(chain, "eventmanager", em)
|
||||
result = asyncio.run(chain.async_recognize_by_meta(meta))
|
||||
|
||||
assert result is remote
|
||||
assert recognize_calls[-1].title == "晴天"
|
||||
@@ -193,10 +200,11 @@ def test_plugin_first_keeps_fallback_when_help_unidentified(monkeypatch):
|
||||
"title": "晴天",
|
||||
"name": "另一个晴天",
|
||||
})
|
||||
with patch("app.chain.media.eventmanager") as em, \
|
||||
patch("app.runtime.config.settings.RECOGNIZE_PLUGIN_FIRST", True):
|
||||
em.check.return_value = True
|
||||
em.send_event.return_value = event
|
||||
em = MagicMock()
|
||||
em.check.return_value = True
|
||||
em.send_event.return_value = event
|
||||
monkeypatch.setattr(chain, "eventmanager", em)
|
||||
with patch("app.runtime.config.settings.RECOGNIZE_PLUGIN_FIRST", True):
|
||||
result = chain.recognize_by_meta(meta)
|
||||
|
||||
assert result is fallback
|
||||
|
||||
Reference in New Issue
Block a user