Skip to main content
Glama

NijiVoice-MCP

by ryoooo
test_api.py13 kB
"""Test suite for NijiVoiceClient in api.py.""" import os import pytest import json from unittest.mock import patch, AsyncMock, MagicMock import httpx import pytest_asyncio from nijivoice.api import NijiVoiceClient from nijivoice.models import VoiceActor, VoiceGenerationRequest, Balance from nijivoice.exceptions import NijiVoiceAPIError @pytest.fixture def mock_env(): """Mock environment variables.""" with patch.dict(os.environ, {"NIJIVOICE_API_KEY": "test-api-key"}): yield @pytest.fixture def mock_response(): """Create a mock response.""" mock = MagicMock() mock.status_code = 200 mock.text = "Success" return mock @pytest.fixture def client(): """Create a NijiVoiceClient instance.""" return NijiVoiceClient(api_key="test-api-key") class TestNijiVoiceClient: """Test cases for NijiVoiceClient.""" def test_init_with_api_key(self): """Test initialization with api_key parameter.""" client = NijiVoiceClient(api_key="test-api-key") assert client.api_key == "test-api-key" assert client.timeout == 30.0 assert client.headers == { "x-api-key": "test-api-key", "Accept": "application/json", } def test_init_without_api_key(self, mock_env): """Test initialization without api_key parameter.""" client = NijiVoiceClient() assert client.api_key == "test-api-key" assert client.timeout == 30.0 def test_init_with_custom_timeout(self): """Test initialization with custom timeout.""" client = NijiVoiceClient(api_key="test-api-key", timeout=60.0) assert client.timeout == 60.0 def test_init_without_api_key_and_env(self): """Test initialization without api_key parameter and environment variable.""" with patch.dict(os.environ, {}, clear=True): with pytest.raises(ValueError) as excinfo: NijiVoiceClient() assert "APIキーが指定されていません" in str(excinfo.value) @pytest.mark.asyncio async def test_get_voice_actors_success(self, client, mock_response): """Test get_voice_actors successful response.""" # Create mock data voice_actors_data = [ { "id": "actor-id-1", "name": "Actor 1", "gender": "Female", "age": 25 }, { "id": "actor-id-2", "name": "Actor 2", "gender": "Male", "age": 30 } ] mock_response.json.return_value = voice_actors_data # Mock the AsyncClient.get method with patch("httpx.AsyncClient") as mock_client: mock_client.return_value.__aenter__.return_value.get.return_value = mock_response # Call the method result = await client.get_voice_actors() # Verify the result assert len(result) == 2 assert isinstance(result[0], VoiceActor) assert result[0].id == "actor-id-1" assert result[0].name == "Actor 1" assert result[1].id == "actor-id-2" assert result[1].name == "Actor 2" # Verify the request was made correctly mock_client.return_value.__aenter__.return_value.get.assert_called_once_with( f"{client.BASE_URL}/voice-actors", headers=client.headers ) @pytest.mark.asyncio async def test_get_voice_actors_voiceActors_key(self, client, mock_response): """Test get_voice_actors with voiceActors key in response.""" # Create mock data with voiceActors key voice_actors_data = { "voiceActors": [ { "id": "actor-id-1", "name": "Actor 1", "gender": "Female", "age": 25 }, { "id": "actor-id-2", "name": "Actor 2", "gender": "Male", "age": 30 } ] } mock_response.json.return_value = voice_actors_data # Mock the AsyncClient.get method with patch("httpx.AsyncClient") as mock_client: mock_client.return_value.__aenter__.return_value.get.return_value = mock_response # Call the method result = await client.get_voice_actors() # Verify the result assert len(result) == 2 assert isinstance(result[0], VoiceActor) assert result[0].id == "actor-id-1" assert result[0].name == "Actor 1" @pytest.mark.asyncio async def test_get_voice_actors_unexpected_format(self, client, mock_response): """Test get_voice_actors with unexpected data format.""" # Create unexpected data format mock_response.json.return_value = {"unexpectedKey": "unexpected value"} # Mock the AsyncClient.get method with patch("httpx.AsyncClient") as mock_client: mock_client.return_value.__aenter__.return_value.get.return_value = mock_response # Call the method result = await client.get_voice_actors() # Verify the result is an empty list assert isinstance(result, list) assert len(result) == 0 @pytest.mark.asyncio async def test_get_voice_actors_error_response(self, client): """Test get_voice_actors with error response.""" # Create error response error_response = MagicMock() error_response.status_code = 404 error_response.text = "Not Found" # Mock the AsyncClient.get method with patch("httpx.AsyncClient") as mock_client: mock_client.return_value.__aenter__.return_value.get.return_value = error_response # Call the method and expect exception with pytest.raises(NijiVoiceAPIError) as excinfo: await client.get_voice_actors() # Verify the exception assert excinfo.value.status_code == 404 assert "Voice Actor一覧の取得に失敗しました" in str(excinfo.value) @pytest.mark.asyncio async def test_get_voice_actors_timeout(self, client): """Test get_voice_actors with timeout.""" # Mock the AsyncClient.get method to raise TimeoutError with patch("httpx.AsyncClient") as mock_client: mock_client.return_value.__aenter__.return_value.get.side_effect = TimeoutError("Timeout") # Call the method and expect exception with pytest.raises(NijiVoiceAPIError) as excinfo: await client.get_voice_actors() # Verify the exception assert excinfo.value.status_code == 408 assert "APIリクエストがタイムアウトしました" in str(excinfo.value) @pytest.mark.asyncio async def test_get_voice_actors_general_exception(self, client): """Test get_voice_actors with general exception.""" # Mock the AsyncClient.get method to raise Exception with patch("httpx.AsyncClient") as mock_client: mock_client.return_value.__aenter__.return_value.get.side_effect = Exception("Some error") # Call the method and expect exception with pytest.raises(NijiVoiceAPIError) as excinfo: await client.get_voice_actors() # Verify the exception assert excinfo.value.status_code == 500 assert "API呼び出し中にエラーが発生しました" in str(excinfo.value) @pytest.mark.asyncio async def test_generate_voice_success(self, client, mock_response): """Test generate_voice successful response.""" # Create mock response data response_data = { "encoded_voice": "base64_encoded_data", "remaining_credits": 100 } mock_response.json.return_value = response_data # Create request request = VoiceGenerationRequest( id="actor-id-1", script="これはテストです", speed=1.0 ) # Mock the AsyncClient.post method with patch("httpx.AsyncClient") as mock_client: mock_client.return_value.__aenter__.return_value.post.return_value = mock_response # Call the method result = await client.generate_voice(request=request) # Verify the result assert result == response_data # Verify the request was made correctly mock_client.return_value.__aenter__.return_value.post.assert_called_once_with( f"{client.BASE_URL}/voice-actors/{request.id}/generate-voice", headers=client.headers, json=request.model_dump(by_alias=True) ) @pytest.mark.asyncio async def test_generate_voice_error_response(self, client): """Test generate_voice with error response.""" # Create error response error_response = MagicMock() error_response.status_code = 500 error_response.text = "Server Error" # Create request request = VoiceGenerationRequest( id="actor-id-1", script="これはテストです", speed=1.0 ) # Mock the AsyncClient.post method with patch("httpx.AsyncClient") as mock_client: mock_client.return_value.__aenter__.return_value.post.return_value = error_response # Call the method and expect exception with pytest.raises(NijiVoiceAPIError) as excinfo: await client.generate_voice(request=request) # Verify the exception assert excinfo.value.status_code == 500 assert "音声生成に失敗しました" in str(excinfo.value) @pytest.mark.asyncio async def test_get_balance_success(self, client, mock_response): """Test get_balance successful response.""" # Create mock response data response_data = {"balance": 500} mock_response.json.return_value = response_data # Mock the AsyncClient.get method with patch("httpx.AsyncClient") as mock_client: mock_client.return_value.__aenter__.return_value.get.return_value = mock_response # Call the method result = await client.get_balance() # Verify the result assert isinstance(result, Balance) assert result.balance == 500 assert result.get_credit() == 500 # Verify the request was made correctly mock_client.return_value.__aenter__.return_value.get.assert_called_once_with( f"{client.BASE_URL}/balances", headers=client.headers ) @pytest.mark.asyncio async def test_get_balance_complex_response(self, client, mock_response): """Test get_balance with complex response structure.""" # Create mock response data with complex structure response_data = { "balances": { "remainingBalance": 500, "credits": [ {"balance": 300, "type": "regular"}, {"balance": 200, "type": "bonus"} ] } } mock_response.json.return_value = response_data # Mock the AsyncClient.get method with patch("httpx.AsyncClient") as mock_client: mock_client.return_value.__aenter__.return_value.get.return_value = mock_response # Call the method result = await client.get_balance() # Verify the result assert isinstance(result, Balance) assert result.balances == response_data["balances"] assert result.get_credit() == 500 @pytest.mark.asyncio async def test_get_balance_error_response(self, client): """Test get_balance with error response.""" # Create error response error_response = MagicMock() error_response.status_code = 403 error_response.text = "Forbidden" # Mock the AsyncClient.get method with patch("httpx.AsyncClient") as mock_client: mock_client.return_value.__aenter__.return_value.get.return_value = error_response # Call the method and expect exception with pytest.raises(NijiVoiceAPIError) as excinfo: await client.get_balance() # Verify the exception assert excinfo.value.status_code == 403 assert "クレジット残高の取得に失敗しました" in str(excinfo.value)

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/ryoooo/nijivoice-mcp'

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