""" 测试接口模块 """ import os import sys import unittest from unittest import mock from io import StringIO # 添加项目根目录到Python路径 sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) from src.interface.api import TFTStrategistAPI from src.interface.cli import TFTCommandLine from src.recommendation.recommendation_engine import TeamComposition from src.data_provider import DataLoader, DataQueryAPI class TestTFTStrategistAPI(unittest.TestCase): """测试TFTStrategistAPI类""" def setUp(self): """测试前准备""" # 模拟DataLoader self.mock_loader = mock.Mock() self.mock_loader.load_all_data.return_value = True # 模拟加载的数据 self.job_data = { "version": "15.7", "data": [ { "jobId": "10157", "name": "重装战士", "level": { "2": "16%最大生命值", "4": "32%最大生命值", } } ] } self.race_data = { "version": "15.7", "data": [ { "raceId": "10154", "name": "街头恶魔", "level": { "3": "+6% 生命值", "5": "+10% 生命值", } } ] } self.chess_data = { "version": "15.7", "data": [ { "chessId": "10275", "displayName": "布兰德", "raceIds": "10154", "jobIds": "10172", "price": "4" }, { "chessId": "10276", "displayName": "阿利斯塔", "raceIds": "", "jobIds": "10157", "price": "3" } ] } # 设置模拟数据返回 self.mock_loader.get_data.side_effect = lambda data_type: { 'job': self.job_data, 'race': self.race_data, 'chess': self.chess_data }.get(data_type) # 模拟DataQueryAPI self.mock_api = mock.Mock() self.mock_api.get_version.return_value = "15.7" self.mock_api.get_all_jobs.return_value = self.job_data["data"] self.mock_api.get_all_races.return_value = self.race_data["data"] self.mock_api.get_all_chess.return_value = self.chess_data["data"] self.mock_api.load_all_data.return_value = True # 模拟RecommendationEngine self.mock_recommendation_engine = mock.Mock() # 创建API实例,并注入模拟对象 with mock.patch('src.interface.api.DataQueryAPI', return_value=self.mock_api): with mock.patch('src.interface.api.RecommendationEngine', return_value=self.mock_recommendation_engine): self.api = TFTStrategistAPI(use_local_data=True) def test_get_version(self): """测试获取版本号""" version = self.api.get_version() self.assertEqual(version, "15.7") # 由于在初始化和测试中都会调用get_version,所以不再断言调用次数 def test_customize_scoring(self): """测试自定义评分系统""" # 捕获调用customize_scoring时的参数 with mock.patch.object(self.api.scorer, 'customize_scoring') as mock_customize: self.api.customize_scoring(synergy_level_weight=2.0) mock_customize.assert_called_once_with(synergy_level_weight=2.0) def test_get_scoring_config(self): """测试获取评分配置""" config = self.api.get_scoring_config() self.assertIn('synergy_level_weight', config) self.assertIn('synergy_count_weight', config) self.assertIn('chess_cost_weight', config) def test_recommend_team(self): """测试推荐阵容""" # 创建模拟的TeamComposition team = TeamComposition() team.chess_list = [{"displayName": "布兰德", "price": "4"}] team.score = 10.5 # 设置recommend_team的返回值 self.mock_recommendation_engine.recommend_team.return_value = [team] # 调用API teams = self.api.recommend_team(population=8) # 验证结果 self.assertEqual(len(teams), 1) self.assertEqual(teams[0]['score'], 10.5) self.assertEqual(len(teams[0]['chess_list']), 1) self.assertEqual(teams[0]['chess_list'][0]['displayName'], "布兰德") # 验证调用参数 self.mock_recommendation_engine.recommend_team.assert_called_once_with( population=8, required_synergies=[], required_chess=[], max_results=5 ) def test_score_team(self): """测试计算阵容评分""" # 设置score_team的返回值 self.api.scorer.score_team = mock.Mock(return_value=15.5) # 创建阵容数据 team_dict = { 'chess_list': [{"displayName": "布兰德", "price": "4"}] } # 调用API score = self.api.score_team(team_dict) # 验证结果 self.assertEqual(score, 15.5) class TestTFTCommandLine(unittest.TestCase): """测试TFTCommandLine类""" @mock.patch('src.interface.cli.input', side_effect=['', '']) @mock.patch('sys.stdout', new_callable=StringIO) def test_run_without_input(self, mock_stdout, mock_input): """测试不输入羁绊和棋子时的运行""" # 模拟RecommendationEngine返回空阵容列表 mock_engine = mock.Mock() mock_engine.recommend_team.return_value = [] # 模拟API mock_api = mock.Mock() mock_api.get_version.return_value = "15.7" # 使用模拟对象创建CLI实例 with mock.patch('src.interface.cli.DataQueryAPI', return_value=mock_api): with mock.patch('src.interface.cli.RecommendationEngine', return_value=mock_engine): cli = TFTCommandLine() # 捕获参数解析错误 with mock.patch('argparse.ArgumentParser.parse_args', return_value=mock.MagicMock( population=9, results=3, level_weight=1.0, count_weight=0.5, cost_weight=0.1)): cli.run() # 验证输出包含版本信息 output = mock_stdout.getvalue() self.assertIn("云顶之弈阵容推荐器", output) self.assertIn("15.7", output) # 版本号 self.assertIn("阵容人口: 9", output) # 验证推荐调用 mock_engine.recommend_team.assert_called_once_with( population=9, required_synergies=[], required_chess=[], max_results=3 ) if __name__ == '__main__': unittest.main()