-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_async_base_operations.py
More file actions
130 lines (97 loc) · 4.31 KB
/
Copy pathtest_async_base_operations.py
File metadata and controls
130 lines (97 loc) · 4.31 KB
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
"""Tests for async base operations."""
from unittest.mock import AsyncMock, MagicMock
import pytest
from bloomy.utils.async_base_operations import AsyncBaseOperations
class MockAsyncHTTPClient:
"""Mock async HTTP client for testing."""
def __init__(self) -> None:
"""Initialize mock async HTTP client with base URL and headers."""
self.base_url = "https://app.bloomgrowth.com/api/v1"
self.headers = {"Authorization": "Bearer test-token"}
self.get = AsyncMock()
class TestAsyncBaseOperations:
"""Test cases for AsyncBaseOperations."""
@pytest.mark.asyncio
async def test_user_id_property_default(self) -> None:
"""Test async user_id property with default fetch."""
client = MockAsyncHTTPClient()
# Mock the API response
mock_response = MagicMock()
mock_response.json.return_value = {"Id": 789}
mock_response.raise_for_status = MagicMock()
client.get.return_value = mock_response
ops = AsyncBaseOperations(client)
# First access should fetch from API
user_id = await ops.get_user_id()
assert user_id == 789
assert ops._user_id == 789
# Second access should use cached value
client.get.reset_mock()
user_id2 = await ops.get_user_id()
assert user_id2 == 789
client.get.assert_not_called()
@pytest.mark.asyncio
async def test_user_id_property_setter(self) -> None:
"""Test setting user_id property."""
client = MockAsyncHTTPClient()
ops = AsyncBaseOperations(client)
# Set user ID directly
ops.user_id = 999
assert ops._user_id == 999
# Should use set value, not fetch from API
user_id = await ops.get_user_id()
assert user_id == 999
client.get.assert_not_called()
# Also test property access
assert ops.user_id == 999
@pytest.mark.asyncio
async def test_get_default_user_id(self) -> None:
"""Test _get_default_user_id method."""
client = MockAsyncHTTPClient()
# Mock the API response
mock_response = MagicMock()
mock_response.json.return_value = {"Id": 555}
mock_response.raise_for_status = MagicMock()
client.get.return_value = mock_response
ops = AsyncBaseOperations(client)
# Call the protected method directly
user_id = await ops._get_default_user_id()
assert user_id == 555
# Verify API call
client.get.assert_called_once_with("users/mine")
@pytest.mark.asyncio
async def test_process_bulk_async_preserves_input_order(self) -> None:
"""Gather results stay in input order even when later items finish first."""
import asyncio
client = MockAsyncHTTPClient()
ops = AsyncBaseOperations(client)
# Delays inverted so item 0 finishes last, item 2 finishes first.
delays = {0: 0.05, 1: 0.02, 2: 0.01}
async def create_func(item_data: dict) -> str:
await asyncio.sleep(delays[item_data["index"]])
return f"created-{item_data['index']}"
items = [{"index": i, "title": f"item-{i}"} for i in range(3)]
result = await ops._process_bulk_async(
items, create_func, required_fields=["title"], max_concurrent=3
)
assert result.failed == []
assert result.successful == ["created-0", "created-1", "created-2"]
@pytest.mark.asyncio
async def test_process_bulk_async_failure_index_matches_input(self) -> None:
"""Failed items keep the original input index without post-sort."""
import asyncio
client = MockAsyncHTTPClient()
ops = AsyncBaseOperations(client)
async def create_func(item_data: dict) -> str:
await asyncio.sleep(0.01 if item_data["index"] != 0 else 0.03)
if item_data["index"] == 1:
raise ValueError("boom")
return f"created-{item_data['index']}"
items = [{"index": i, "title": f"item-{i}"} for i in range(3)]
result = await ops._process_bulk_async(
items, create_func, required_fields=["title"], max_concurrent=3
)
assert result.successful == ["created-0", "created-2"]
assert len(result.failed) == 1
assert result.failed[0].index == 1
assert "boom" in result.failed[0].error