import unittest from unittest.mock import MagicMock, patch from action_executor import ActionExecutor def make_executor(): rcon = MagicMock() rcon.lua.return_value = "OK" ex = ActionExecutor(rcon) return ex, rcon class TestBuildSmeltingLine(unittest.TestCase): def test_build_smelting_line_calls_place_entity_n_times(self): ex, rcon = make_executor() with patch.object(ex, "place_entity", return_value=(True, "stone-furnace 배치 (0, 0)")) as mock_place, \ patch.object(ex, "_auto_bootstrap_furnace", return_value=(True, "OK")), \ patch.object(ex, "move", return_value=(True, "도착")): ok, msg = ex.build_smelting_line(ore="iron-ore", x=0, y=0, furnace_count=3) self.assertTrue(ok) self.assertEqual(mock_place.call_count, 3) def test_build_smelting_line_default_furnace_count(self): ex, rcon = make_executor() with patch.object(ex, "place_entity", return_value=(True, "stone-furnace 배치 (0, 0)")), \ patch.object(ex, "_auto_bootstrap_furnace", return_value=(True, "OK")), \ patch.object(ex, "move", return_value=(True, "도착")): ok, msg = ex.build_smelting_line(ore="iron-ore", x=0, y=0) self.assertTrue(ok) def test_build_smelting_line_partial_failure_still_reports(self): ex, rcon = make_executor() # 첫 번째 성공, 두 번째 실패, 세 번째 성공 side_effects = [(True, "stone-furnace 배치 (0, 0)"), (False, "막힘"), (True, "stone-furnace 배치 (0, 6)")] with patch.object(ex, "place_entity", side_effect=side_effects), \ patch.object(ex, "_auto_bootstrap_furnace", return_value=(True, "OK")), \ patch.object(ex, "move", return_value=(True, "도착")): ok, msg = ex.build_smelting_line(ore="iron-ore", x=0, y=0, furnace_count=3) # 2개 성공이므로 전체 실패가 아님 self.assertTrue(ok) self.assertIn("2개 배치", msg) def test_build_smelting_line_all_fail_returns_false(self): ex, rcon = make_executor() with patch.object(ex, "place_entity", return_value=(False, "막힘")), \ patch.object(ex, "_auto_bootstrap_furnace", return_value=(True, "OK")), \ patch.object(ex, "move", return_value=(True, "도착")): ok, msg = ex.build_smelting_line(ore="iron-ore", x=0, y=0, furnace_count=2) self.assertFalse(ok) def test_build_smelting_line_via_execute_dispatch(self): ex, rcon = make_executor() with patch.object(ex, "build_smelting_line", return_value=(True, "2개 배치 완료")) as mock_bsl: ok, msg = ex.execute({ "action": "build_smelting_line", "params": {"ore": "iron-ore", "x": -90, "y": -70, "furnace_count": 4}, }) mock_bsl.assert_called_once_with(ore="iron-ore", x=-90, y=-70, furnace_count=4) self.assertTrue(ok) if __name__ == "__main__": unittest.main()