File size: 6,309 Bytes
88d205f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/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()