Skip to main content
Glama
test_tools_simple.py7.43 kB
""" 简化的MCP工具模块单元测试 """ import pytest from unittest.mock import Mock, patch import ccxt from binance_mcp.tools import BinanceMCPTools, handle_ccxt_error @pytest.mark.unit class TestBinanceMCPTools: """BinanceMCPTools单元测试""" def test_init_with_config_manager(self, config_manager): """测试使用配置管理器初始化""" tools = BinanceMCPTools(config_manager) assert tools.config_manager == config_manager def test_get_exchange_invalid_account(self, config_manager): """测试获取不存在账户的exchange""" tools = BinanceMCPTools(config_manager) with pytest.raises(ValueError, match="账户 .* 不存在"): tools._get_exchange('nonexistent_account') @patch('binance_mcp.tools.exchange_factory.create_exchange') def test_get_exchange_success(self, mock_create_exchange, config_manager): """测试成功获取exchange实例""" # 添加测试账户 config_manager.add_account( 'test_account', 'test_api_key_123', 'test_secret_456', True, '测试账户' ) # 模拟exchange创建 mock_exchange = Mock() mock_create_exchange.return_value = mock_exchange tools = BinanceMCPTools(config_manager) result = tools._get_exchange('test_account') assert result == mock_exchange mock_create_exchange.assert_called_once() def test_create_spot_order_success(self, tools_with_mock_exchange): """测试成功创建现货订单""" mock_exchange = tools_with_mock_exchange._get_exchange('test_account') mock_exchange.create_order.return_value = { 'id': 'test_order_123', 'symbol': 'BTC/USDT', 'type': 'limit', 'side': 'buy', 'amount': 0.01, 'price': 50000, 'status': 'open' } result = tools_with_mock_exchange.create_spot_order( account_id='test_account', symbol='BTC/USDT', side='buy', amount=0.01, price=50000, order_type='limit' ) assert result['id'] == 'test_order_123' assert result['symbol'] == 'BTC/USDT' assert result['side'] == 'buy' mock_exchange.create_order.assert_called_once_with( 'BTC/USDT', 'limit', 'buy', 0.01, 50000, {} ) def test_cancel_order_success(self, tools_with_mock_exchange): """测试成功取消订单""" mock_exchange = tools_with_mock_exchange._get_exchange('test_account') mock_exchange.cancel_order.return_value = { 'id': 'test_order_123', 'status': 'canceled' } result = tools_with_mock_exchange.cancel_order( account_id='test_account', order_id='test_order_123', symbol='BTC/USDT' ) assert result['id'] == 'test_order_123' assert result['status'] == 'canceled' mock_exchange.cancel_order.assert_called_once_with( 'test_order_123', 'BTC/USDT', {} ) def test_get_balance_success(self, tools_with_mock_exchange): """测试成功获取余额""" mock_exchange = tools_with_mock_exchange._get_exchange('test_account') mock_exchange.fetch_balance.return_value = { 'BTC': {'free': 1.0, 'used': 0.0, 'total': 1.0}, 'USDT': {'free': 10000.0, 'used': 0.0, 'total': 10000.0} } result = tools_with_mock_exchange.get_balance('test_account') assert 'BTC' in result assert 'USDT' in result assert result['BTC']['free'] == 1.0 assert result['USDT']['free'] == 10000.0 mock_exchange.fetch_balance.assert_called_once() def test_get_ticker_success(self, tools_with_mock_exchange): """测试成功获取价格行情""" # get_ticker会自动使用第一个配置的账户 mock_exchange = tools_with_mock_exchange._get_exchange('test_account') mock_exchange.fetch_ticker.return_value = { 'symbol': 'BTC/USDT', 'last': 50000, 'bid': 49999, 'ask': 50001, 'volume': 12345.67 } result = tools_with_mock_exchange.get_ticker(symbol='BTC/USDT') assert result['symbol'] == 'BTC/USDT' assert result['last'] == 50000 assert result['bid'] == 49999 assert result['ask'] == 50001 mock_exchange.fetch_ticker.assert_called_once_with('BTC/USDT', {}) @pytest.mark.unit class TestHandleCcxtError: """测试ccxt错误处理装饰器""" def test_handle_ccxt_error_decorator_success(self): """测试装饰器在正常情况下的行为""" @handle_ccxt_error def test_function(): return "success" result = test_function() assert result == "success" def test_handle_ccxt_error_decorator_network_error(self): """测试网络错误处理""" @handle_ccxt_error def test_function(): raise ccxt.NetworkError("网络连接失败") with pytest.raises(Exception) as exc_info: test_function() # 验证错误信息包含网络错误提示 assert "网络连接失败" in str(exc_info.value) def test_handle_ccxt_error_decorator_auth_error(self): """测试认证错误处理""" @handle_ccxt_error def test_function(): raise ccxt.AuthenticationError("API密钥无效") with pytest.raises(Exception) as exc_info: test_function() assert "API密钥无效" in str(exc_info.value) def test_handle_ccxt_error_decorator_generic_error(self): """测试通用错误处理""" @handle_ccxt_error def test_function(): raise ValueError("普通错误") # 非ccxt错误会被包装成RuntimeError with pytest.raises(RuntimeError, match="工具执行失败"): test_function() @pytest.mark.unit class TestToolsErrorHandling: """测试工具类的错误处理""" def test_create_order_with_ccxt_error(self, tools_with_mock_exchange): """测试订单创建时的ccxt错误处理""" mock_exchange = tools_with_mock_exchange._get_exchange('test_account') mock_exchange.create_order.side_effect = ccxt.InsufficientFunds("余额不足") with pytest.raises(Exception) as exc_info: tools_with_mock_exchange.create_spot_order( 'test_account', 'BTC/USDT', 'buy', 0.01, 50000 ) assert "余额不足" in str(exc_info.value) def test_get_balance_with_auth_error(self, tools_with_mock_exchange): """测试获取余额时的认证错误""" mock_exchange = tools_with_mock_exchange._get_exchange('test_account') mock_exchange.fetch_balance.side_effect = ccxt.AuthenticationError("API密钥无效") with pytest.raises(Exception) as exc_info: tools_with_mock_exchange.get_balance('test_account') assert "API密钥无效" in str(exc_info.value)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/shanrichard/binance-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server