Files
cultivation-world-simulator/tests/test_action_combat.py
2025-12-20 17:13:53 +08:00

78 lines
3.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import pytest
from unittest.mock import MagicMock, patch, AsyncMock
from src.classes.action.attack import Attack
from src.classes.action_runtime import ActionStatus
class TestActionCombat:
@pytest.fixture
def target_avatar(self, dummy_avatar):
"""创建一个靶子角色"""
target = MagicMock()
target.name = "TargetDummy"
target.id = "target_id"
target.hp = MagicMock()
target.hp.current = 100
target.hp.max = 100
target.increase_weapon_proficiency = MagicMock()
return target
@patch("src.classes.action.attack.decide_battle")
def test_attack_execution(self, mock_decide, dummy_avatar, target_avatar):
"""测试攻击执行:扣除 HP"""
# Mock decide_battle 返回 (winner, loser, loser_dmg, winner_dmg)
# 假设 dummy 赢了Target 掉了 10 点血dummy 掉了 2 点
mock_decide.return_value = (dummy_avatar, target_avatar, 10, 2)
# 注入 target 到 world
dummy_avatar.world.avatar_manager.avatars = {target_avatar.name: target_avatar}
# Mock HP 为 MagicMock 以便 assert_called
dummy_avatar.hp = MagicMock()
action = Attack(dummy_avatar, dummy_avatar.world)
action._execute(avatar_name="TargetDummy")
# 验证伤害应用
target_avatar.hp.reduce.assert_called_with(10)
dummy_avatar.hp.reduce.assert_called_with(2)
# 验证熟练度增加 (虽然是随机的,但 mock 了 uniform 就好了,或者只验证调用)
assert dummy_avatar.weapon.get_detailed_info.called or True # 只是确保流程跑通
@patch("src.classes.action.attack.handle_death") # 这个是在 death.py 里的
@patch("src.classes.battle.handle_battle_finish", new_callable=AsyncMock)
def test_attack_finish(self, mock_battle_finish, mock_handle_death, dummy_avatar, target_avatar):
"""测试战斗结束回调"""
# 注入 target
dummy_avatar.world.avatar_manager.avatars = {target_avatar.name: target_avatar}
action = Attack(dummy_avatar, dummy_avatar.world)
# 设置 _last_result (通常由 execute 设置)
action._last_result = (dummy_avatar, target_avatar, 10, 2)
action._start_event_content = "Start Battle"
# 运行 finish
import asyncio
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(action.finish(avatar_name="TargetDummy"))
# 验证调用了 handle_battle_finish
mock_battle_finish.assert_called_once()
args, kwargs = mock_battle_finish.call_args
assert args[1] == dummy_avatar # winner
assert args[2] == target_avatar # loser
def test_can_start_missing_target(self, dummy_avatar):
"""测试目标不存在"""
dummy_avatar.world.avatar_manager.avatars = {}
action = Attack(dummy_avatar, dummy_avatar.world)
ok, reason = action.can_start("Ghost")
assert ok is False
assert reason == "目标不存在"