#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Unit tests for the AI Review Service """ import unittest from unittest.mock import patch, MagicMock import os import sys from pathlib import Path # Add the project root directory to the Python path project_root = Path(__file__).resolve().parent.parent sys.path.insert(0, str(project_root)) from src.mcp.ai_review import AIReviewService class TestAIReviewService(unittest.TestCase): """Test cases for the AIReviewService class""" def setUp(self): """Set up test fixtures""" # Mock environment variables self.env_patcher = patch.dict('os.environ', {'ANTHROPIC_API_KEY': 'test_api_key'}) self.env_patcher.start() # Create the service self.service = AIReviewService() def tearDown(self): """Tear down test fixtures""" self.env_patcher.stop() def test_init(self): """Test initialization of the service""" self.assertIsNotNone(self.service) self.assertEqual(self.service.api_key, 'test_api_key') self.assertTrue(self.service.is_available()) def test_is_available(self): """Test is_available method""" # With API key self.assertTrue(self.service.is_available()) # Without API key with patch.dict('os.environ', {}, clear=True): service = AIReviewService() self.assertFalse(service.is_available()) @patch('anthropic.Anthropic') def test_review_code(self, mock_anthropic): """Test review_code method""" # Mock the Anthropic client mock_client = MagicMock() mock_anthropic.return_value = mock_client # Mock the response mock_response = MagicMock() mock_content = MagicMock() mock_content.text = "# Code Review\n\n## Code Quality\nThe code is well-structured.\n\n## Potential Issues\nLine 10: Variable 'x' is not used." mock_response.content = [mock_content] mock_client.messages.create.return_value = mock_response # Test the method result = self.service.review_code( file_path="test.py", file_content="def test():\n x = 1\n return 2", language="Python" ) # Verify the result self.assertEqual(result['status'], 'success') self.assertEqual(result['review_text'], mock_content.text) self.assertIn('suggestions', result) @patch('anthropic.Anthropic') def test_review_code_error(self, mock_anthropic): """Test review_code method with error""" # Mock the Anthropic client mock_client = MagicMock() mock_anthropic.return_value = mock_client # Mock an error mock_client.messages.create.side_effect = Exception("API error") # Test the method result = self.service.review_code( file_path="test.py", file_content="def test():\n return 1", language="Python" ) # Verify the result self.assertEqual(result['status'], 'error') self.assertEqual(result['error'], 'API error') self.assertEqual(result['suggestions'], []) def test_review_code_unavailable(self): """Test review_code method when service is unavailable""" # Create a service without API key with patch.dict('os.environ', {}, clear=True): service = AIReviewService() # Test the method result = service.review_code( file_path="test.py", file_content="def test():\n return 1", language="Python" ) # Verify the result self.assertEqual(result['status'], 'error') self.assertIn('AI review service is not available', result['error']) self.assertEqual(result['suggestions'], []) @patch('anthropic.Anthropic') @patch('builtins.open', new_callable=unittest.mock.mock_open, read_data="def test():\n return 1") def test_review_repository(self, mock_open, mock_anthropic): """Test review_repository method""" # Mock the Anthropic client mock_client = MagicMock() mock_anthropic.return_value = mock_client # Mock the response for file review mock_file_response = MagicMock() mock_file_content = MagicMock() mock_file_content.text = "# Code Review\n\n## Code Quality\nThe code is well-structured." mock_file_response.content = [mock_file_content] # Mock the response for repository summary mock_summary_response = MagicMock() mock_summary_content = MagicMock() mock_summary_content.text = "# Repository Review\n\nOverall, the code quality is good." mock_summary_response.content = [mock_summary_content] # Set up the mock to return different responses mock_client.messages.create.side_effect = [mock_file_response, mock_summary_response] # Test the method result = self.service.review_repository( repo_path="/test/repo", files=["test.py"], languages=["Python"] ) # Verify the result self.assertEqual(result['status'], 'success') self.assertIn('reviews', result) self.assertIn('test.py', result['reviews']) self.assertEqual(result['summary'], mock_summary_content.text) def test_get_language_from_extension(self): """Test _get_language_from_extension method""" self.assertEqual(self.service._get_language_from_extension(".py"), "Python") self.assertEqual(self.service._get_language_from_extension(".js"), "JavaScript") self.assertEqual(self.service._get_language_from_extension(".ts"), "TypeScript") self.assertEqual(self.service._get_language_from_extension(".java"), "Java") self.assertEqual(self.service._get_language_from_extension(".go"), "Go") self.assertEqual(self.service._get_language_from_extension(".rs"), "Rust") self.assertIsNone(self.service._get_language_from_extension(".unknown")) if __name__ == "__main__": unittest.main()