|
1 | 1 | from openai import APIError, OpenAI |
2 | 2 | import pytest |
| 3 | +from unittest.mock import patch, Mock |
3 | 4 |
|
4 | 5 | from apps.integrations.openai.client import OpenAIClient, OPEN_AI_API_ERROR_MSG |
5 | 6 | from apps.integrations.openai.exceptions import OpenAIClientException |
|
8 | 9 |
|
9 | 10 |
|
10 | 11 | class TestOpenAIClientGetSaasIdeas: |
11 | | - def test_success(self, mocker, openai_completion_mock, open_ai_completion_response_factory): |
| 12 | + @patch('apps.integrations.openai.client.settings') |
| 13 | + @patch.object(OpenAI, '__new__') |
| 14 | + def test_success(self, mock_openai_new, mock_settings, open_ai_completion_response_factory): |
| 15 | + OpenAIClient._client = None |
| 16 | + mock_settings.OPENAI_API_KEY = 'sk-test-key' |
| 17 | + mock_settings.OPENAI_MODEL = 'gpt-3.5-turbo' |
| 18 | + |
12 | 19 | response_data = open_ai_completion_response_factory.create() |
13 | | - # Create a mock response object that mimics the chat completions API structure |
14 | | - mock_response = mocker.Mock() |
15 | | - mock_response.id = response_data["id"] |
16 | | - mock_response.object = response_data["object"] |
17 | | - mock_response.created = response_data["created"] |
18 | | - mock_response.model = response_data["model"] |
19 | | - # Chat completions API uses message.content instead of text |
| 20 | + mock_response = Mock() |
20 | 21 | mock_response.choices = [ |
21 | | - mocker.Mock( |
22 | | - message=mocker.Mock(content=choice["text"]), |
| 22 | + Mock( |
| 23 | + message=Mock(content=choice["text"]), |
23 | 24 | index=choice["index"], |
24 | 25 | finish_reason=choice["finish_reason"], |
25 | 26 | ) |
26 | 27 | for choice in response_data["choices"] |
27 | 28 | ] |
28 | | - mock_response.usage = mocker.Mock( |
29 | | - prompt_tokens=response_data["usage"]["prompt_tokens"], |
30 | | - completion_tokens=response_data["usage"]["completion_tokens"], |
31 | | - total_tokens=response_data["usage"]["total_tokens"], |
32 | | - ) |
33 | 29 |
|
34 | | - openai_completion_mock.return_value = mock_response |
35 | | - keywords = ['fitness', 'ai'] |
| 30 | + mock_client = Mock() |
| 31 | + mock_client.chat.completions.create.return_value = mock_response |
| 32 | + mock_openai_new.return_value = mock_client |
36 | 33 |
|
| 34 | + keywords = ['fitness', 'ai'] |
37 | 35 | result = OpenAIClient.get_saas_ideas(keywords) |
38 | 36 |
|
39 | | - # The method uses chat.completions.create, not completions.create |
40 | | - # Verify it was called (the exact parameters depend on model fallback logic) |
41 | | - assert openai_completion_mock.called |
42 | | - # Result should be a string (the text content) |
| 37 | + assert mock_client.chat.completions.create.called |
43 | 38 | assert isinstance(result, str) |
44 | 39 | assert len(result) > 0 |
45 | 40 |
|
46 | | - def test_api_exception(self, mocker): |
47 | | - # Reset the client singleton to ensure fresh mock |
| 41 | + @patch('apps.integrations.openai.client.settings') |
| 42 | + @patch.object(OpenAI, '__new__') |
| 43 | + def test_api_exception(self, mock_openai_new, mock_settings): |
48 | 44 | OpenAIClient._client = None |
| 45 | + mock_settings.OPENAI_API_KEY = 'sk-test-key' |
| 46 | + mock_settings.OPENAI_MODEL = 'gpt-3.5-turbo' |
49 | 47 |
|
50 | | - # Mock the OpenAI client to raise APIError on both paths |
51 | 48 | api_error = APIError(message="The server had an error while processing your request.", request=None, body=None) |
52 | 49 |
|
53 | | - # Create a mock client that raises errors on both completion paths |
54 | | - mock_client = mocker.Mock() |
55 | | - mock_chat = mocker.Mock() |
56 | | - mock_completions_chat = mocker.Mock() |
57 | | - mock_completions_chat.create.side_effect = api_error |
58 | | - mock_chat.completions = mock_completions_chat |
59 | | - mock_client.chat = mock_chat |
60 | | - |
61 | | - # Mock completions.create for instruct models |
62 | | - mock_completions = mocker.Mock() |
63 | | - mock_completions.create.side_effect = api_error |
64 | | - mock_client.completions = mock_completions |
65 | | - |
66 | | - # Patch OpenAI to return our mock |
67 | | - mocker.patch.object(OpenAI, '__new__', return_value=mock_client) |
| 50 | + mock_client = Mock() |
| 51 | + mock_client.chat.completions.create.side_effect = api_error |
| 52 | + mock_openai_new.return_value = mock_client |
68 | 53 |
|
69 | 54 | with pytest.raises(OpenAIClientException) as error: |
70 | 55 | OpenAIClient.get_saas_ideas(['idea']) |
|
0 commit comments