mcp-proxy-adapter 2.1.1__py3-none-any.whl → 2.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mcp_proxy_adapter-2.1.1.dist-info → mcp_proxy_adapter-2.1.3.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-2.1.3.dist-info/RECORD +18 -0
- mcp_proxy_adapter-2.1.3.dist-info/top_level.txt +1 -0
- docs/README.md +0 -172
- docs/README_ru.md +0 -172
- docs/architecture.md +0 -251
- docs/architecture_ru.md +0 -343
- docs/command_development.md +0 -250
- docs/command_development_ru.md +0 -593
- docs/deployment.md +0 -251
- docs/deployment_ru.md +0 -1298
- docs/examples.md +0 -254
- docs/examples_ru.md +0 -401
- docs/mcp_proxy_adapter.md +0 -251
- docs/mcp_proxy_adapter_ru.md +0 -405
- docs/quickstart.md +0 -251
- docs/quickstart_ru.md +0 -397
- docs/testing.md +0 -255
- docs/testing_ru.md +0 -469
- docs/validation_ru.md +0 -287
- examples/analyze_config.py +0 -141
- examples/basic_integration.py +0 -161
- examples/docstring_and_schema_example.py +0 -60
- examples/extension_example.py +0 -60
- examples/help_best_practices.py +0 -67
- examples/help_usage.py +0 -64
- examples/mcp_proxy_client.py +0 -131
- examples/mcp_proxy_config.json +0 -175
- examples/openapi_server.py +0 -369
- examples/project_structure_example.py +0 -47
- examples/testing_example.py +0 -53
- mcp_proxy_adapter-2.1.1.dist-info/RECORD +0 -61
- mcp_proxy_adapter-2.1.1.dist-info/top_level.txt +0 -5
- scripts/code_analyzer/code_analyzer.py +0 -328
- scripts/code_analyzer/register_commands.py +0 -446
- scripts/publish.py +0 -85
- tests/conftest.py +0 -12
- tests/test_adapter.py +0 -529
- tests/test_adapter_coverage.py +0 -274
- tests/test_basic_dispatcher.py +0 -169
- tests/test_command_registry.py +0 -328
- tests/test_examples.py +0 -32
- tests/test_mcp_proxy_adapter.py +0 -568
- tests/test_mcp_proxy_adapter_basic.py +0 -262
- tests/test_part1.py +0 -348
- tests/test_part2.py +0 -524
- tests/test_schema.py +0 -358
- tests/test_simple_adapter.py +0 -251
- {mcp_proxy_adapter-2.1.1.dist-info → mcp_proxy_adapter-2.1.3.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-2.1.1.dist-info → mcp_proxy_adapter-2.1.3.dist-info}/licenses/LICENSE +0 -0
docs/testing_ru.md
DELETED
@@ -1,469 +0,0 @@
|
|
1
|
-
# Руководство по тестированию команд
|
2
|
-
|
3
|
-
В этом руководстве описаны подходы и лучшие практики по тестированию команд, зарегистрированных в Command Registry.
|
4
|
-
|
5
|
-
## Почему важно тестировать команды
|
6
|
-
|
7
|
-
Команды в Command Registry часто представляют собой ключевые бизнес-операции приложения. Их тестирование имеет следующие преимущества:
|
8
|
-
|
9
|
-
1. **Надёжность** - проверка работоспособности команд в различных условиях
|
10
|
-
2. **Документация** - тесты демонстрируют ожидаемое поведение команд
|
11
|
-
3. **Регрессия** - предотвращение появления регрессий при изменениях
|
12
|
-
4. **Рефакторинг** - возможность безопасно улучшать код команд
|
13
|
-
5. **Валидация** - проверка корректной обработки входных параметров и ошибок
|
14
|
-
|
15
|
-
## Уровни тестирования
|
16
|
-
|
17
|
-
### 1. Модульное тестирование (Unit Tests)
|
18
|
-
|
19
|
-
Тестирование отдельных функций-команд в изоляции от других компонентов.
|
20
|
-
|
21
|
-
```python
|
22
|
-
import pytest
|
23
|
-
from myapp.commands.math_commands import add_numbers
|
24
|
-
|
25
|
-
def test_add_numbers_basic():
|
26
|
-
# Базовый сценарий
|
27
|
-
result = add_numbers(5, 3)
|
28
|
-
assert result == 8
|
29
|
-
|
30
|
-
def test_add_numbers_negative():
|
31
|
-
# Работа с отрицательными числами
|
32
|
-
result = add_numbers(-5, 3)
|
33
|
-
assert result == -2
|
34
|
-
|
35
|
-
def test_add_numbers_zero():
|
36
|
-
# Работа с нулями
|
37
|
-
result = add_numbers(0, 0)
|
38
|
-
assert result == 0
|
39
|
-
```
|
40
|
-
|
41
|
-
### 2. Интеграционное тестирование (Integration Tests)
|
42
|
-
|
43
|
-
Тестирование команд с реальными зависимостями или их моками.
|
44
|
-
|
45
|
-
```python
|
46
|
-
import pytest
|
47
|
-
from unittest.mock import MagicMock, patch
|
48
|
-
from myapp.commands.user_commands import get_user_data
|
49
|
-
|
50
|
-
@pytest.fixture
|
51
|
-
def mock_db():
|
52
|
-
"""Фикстура для создания мока базы данных."""
|
53
|
-
mock = MagicMock()
|
54
|
-
mock.users.find_one.return_value = {
|
55
|
-
"id": "user123",
|
56
|
-
"name": "Test User",
|
57
|
-
"email": "test@example.com",
|
58
|
-
"created_at": "2023-01-01T00:00:00Z"
|
59
|
-
}
|
60
|
-
return mock
|
61
|
-
|
62
|
-
@patch("myapp.commands.user_commands.get_database")
|
63
|
-
def test_get_user_data(get_database_mock, mock_db):
|
64
|
-
# Настройка мока
|
65
|
-
get_database_mock.return_value = mock_db
|
66
|
-
|
67
|
-
# Вызов команды
|
68
|
-
result = get_user_data("user123")
|
69
|
-
|
70
|
-
# Проверки
|
71
|
-
assert result["id"] == "user123"
|
72
|
-
assert result["name"] == "Test User"
|
73
|
-
assert "email" in result
|
74
|
-
|
75
|
-
# Проверка вызова БД с правильными параметрами
|
76
|
-
mock_db.users.find_one.assert_called_once_with({"id": "user123"})
|
77
|
-
```
|
78
|
-
|
79
|
-
### 3. Тестирование через Command Registry
|
80
|
-
|
81
|
-
Тестирование команд через интерфейс Command Registry.
|
82
|
-
|
83
|
-
```python
|
84
|
-
import pytest
|
85
|
-
from command_registry import CommandRegistry
|
86
|
-
from command_registry.dispatchers import CommandDispatcher
|
87
|
-
from myapp.commands.math_commands import add_numbers, subtract_numbers
|
88
|
-
|
89
|
-
@pytest.fixture
|
90
|
-
def registry():
|
91
|
-
"""Фикстура для создания CommandRegistry с зарегистрированными командами."""
|
92
|
-
registry = CommandRegistry(CommandDispatcher())
|
93
|
-
registry.register_command("add", add_numbers)
|
94
|
-
registry.register_command("subtract", subtract_numbers)
|
95
|
-
return registry
|
96
|
-
|
97
|
-
def test_registry_add_command(registry):
|
98
|
-
# Выполнение команды через реестр
|
99
|
-
result = registry.execute("add", {"a": 10, "b": 5})
|
100
|
-
assert result == 15
|
101
|
-
|
102
|
-
def test_registry_subtract_command(registry):
|
103
|
-
# Выполнение команды через реестр
|
104
|
-
result = registry.execute("subtract", {"a": 10, "b": 5})
|
105
|
-
assert result == 5
|
106
|
-
|
107
|
-
def test_command_not_found(registry):
|
108
|
-
# Проверка обработки несуществующей команды
|
109
|
-
with pytest.raises(ValueError, match="Command 'multiply' not found"):
|
110
|
-
registry.execute("multiply", {"a": 10, "b": 5})
|
111
|
-
```
|
112
|
-
|
113
|
-
### 4. E2E тестирование через API
|
114
|
-
|
115
|
-
Тестирование команд через внешние интерфейсы (REST, JSON-RPC и т.д.).
|
116
|
-
|
117
|
-
```python
|
118
|
-
import pytest
|
119
|
-
from fastapi.testclient import TestClient
|
120
|
-
from myapp.main import app # FastAPI приложение с зарегистрированными командами
|
121
|
-
|
122
|
-
client = TestClient(app)
|
123
|
-
|
124
|
-
def test_add_numbers_api():
|
125
|
-
response = client.post(
|
126
|
-
"/api/commands/add",
|
127
|
-
json={"a": 10, "b": 5}
|
128
|
-
)
|
129
|
-
assert response.status_code == 200
|
130
|
-
assert response.json() == {"result": 15}
|
131
|
-
|
132
|
-
def test_invalid_params_api():
|
133
|
-
response = client.post(
|
134
|
-
"/api/commands/add",
|
135
|
-
json={"a": "not_a_number", "b": 5}
|
136
|
-
)
|
137
|
-
assert response.status_code == 400
|
138
|
-
assert "error" in response.json()
|
139
|
-
```
|
140
|
-
|
141
|
-
## Тестирование с использованием параметризации
|
142
|
-
|
143
|
-
Параметризация позволяет тестировать множество сценариев с разными входными данными и ожиданиями.
|
144
|
-
|
145
|
-
```python
|
146
|
-
import pytest
|
147
|
-
from myapp.commands.math_commands import calculate_total
|
148
|
-
|
149
|
-
@pytest.mark.parametrize("prices, discount, expected", [
|
150
|
-
([10, 20, 30], 0, 60), # Без скидки
|
151
|
-
([10, 20, 30], 10, 54), # Скидка 10%
|
152
|
-
([100], 50, 50), # Скидка 50%
|
153
|
-
([], 10, 0), # Пустой список
|
154
|
-
])
|
155
|
-
def test_calculate_total(prices, discount, expected):
|
156
|
-
result = calculate_total(prices, discount)
|
157
|
-
assert result == expected
|
158
|
-
|
159
|
-
@pytest.mark.parametrize("invalid_discount", [-10, 110, "invalid"])
|
160
|
-
def test_calculate_total_invalid_discount(invalid_discount):
|
161
|
-
with pytest.raises(ValueError):
|
162
|
-
calculate_total([10, 20], invalid_discount)
|
163
|
-
```
|
164
|
-
|
165
|
-
## Тестирование асинхронных команд
|
166
|
-
|
167
|
-
Для тестирования асинхронных команд используйте pytest-asyncio.
|
168
|
-
|
169
|
-
```python
|
170
|
-
import pytest
|
171
|
-
import asyncio
|
172
|
-
from unittest.mock import AsyncMock, patch
|
173
|
-
from myapp.commands.async_commands import fetch_user_data
|
174
|
-
|
175
|
-
@pytest.mark.asyncio
|
176
|
-
@patch("myapp.commands.async_commands.get_async_database")
|
177
|
-
async def test_fetch_user_data(mock_get_db):
|
178
|
-
# Создаем асинхронный мок
|
179
|
-
mock_db = AsyncMock()
|
180
|
-
mock_db.users.find_one.return_value = {"id": "user123", "name": "Test User"}
|
181
|
-
mock_get_db.return_value = mock_db
|
182
|
-
|
183
|
-
# Вызываем асинхронную команду
|
184
|
-
result = await fetch_user_data("user123")
|
185
|
-
|
186
|
-
# Проверяем результат
|
187
|
-
assert result["id"] == "user123"
|
188
|
-
assert result["name"] == "Test User"
|
189
|
-
|
190
|
-
# Проверяем, что мок был вызван с правильными параметрами
|
191
|
-
mock_db.users.find_one.assert_called_once_with({"id": "user123"})
|
192
|
-
```
|
193
|
-
|
194
|
-
## Тестирование обработки ошибок
|
195
|
-
|
196
|
-
```python
|
197
|
-
import pytest
|
198
|
-
from myapp.commands.user_commands import get_user_data
|
199
|
-
from myapp.exceptions import UserNotFoundError
|
200
|
-
|
201
|
-
@patch("myapp.commands.user_commands.get_database")
|
202
|
-
def test_get_user_data_not_found(mock_get_db):
|
203
|
-
# Настраиваем мок для возврата None (пользователь не найден)
|
204
|
-
db_mock = MagicMock()
|
205
|
-
db_mock.users.find_one.return_value = None
|
206
|
-
mock_get_db.return_value = db_mock
|
207
|
-
|
208
|
-
# Проверяем, что команда вызывает ожидаемое исключение
|
209
|
-
with pytest.raises(UserNotFoundError, match="User with id 'unknown_user' not found"):
|
210
|
-
get_user_data("unknown_user")
|
211
|
-
```
|
212
|
-
|
213
|
-
## Тестирование валидации параметров
|
214
|
-
|
215
|
-
```python
|
216
|
-
import pytest
|
217
|
-
from myapp.commands.product_commands import update_product_price
|
218
|
-
|
219
|
-
def test_update_product_price_negative():
|
220
|
-
# Проверка на отрицательную цену
|
221
|
-
with pytest.raises(ValueError, match="Price cannot be negative"):
|
222
|
-
update_product_price("product123", -10.0)
|
223
|
-
|
224
|
-
def test_update_product_price_invalid_id():
|
225
|
-
# Проверка на пустой идентификатор продукта
|
226
|
-
with pytest.raises(ValueError, match="Product ID cannot be empty"):
|
227
|
-
update_product_price("", 10.0)
|
228
|
-
```
|
229
|
-
|
230
|
-
## Использование фикстур для общих случаев
|
231
|
-
|
232
|
-
```python
|
233
|
-
import pytest
|
234
|
-
from command_registry import CommandRegistry
|
235
|
-
from command_registry.dispatchers import CommandDispatcher
|
236
|
-
import myapp.commands as commands
|
237
|
-
|
238
|
-
@pytest.fixture
|
239
|
-
def registry():
|
240
|
-
"""Создает CommandRegistry со всеми зарегистрированными командами."""
|
241
|
-
registry = CommandRegistry(CommandDispatcher())
|
242
|
-
registry.scan_module(commands)
|
243
|
-
return registry
|
244
|
-
|
245
|
-
@pytest.fixture
|
246
|
-
def mock_database():
|
247
|
-
"""Создает мок базы данных с тестовыми данными."""
|
248
|
-
db = MagicMock()
|
249
|
-
db.users.find_one.return_value = {"id": "user1", "name": "Test User"}
|
250
|
-
db.products.find.return_value = [
|
251
|
-
{"id": "prod1", "name": "Product 1", "price": 10.0},
|
252
|
-
{"id": "prod2", "name": "Product 2", "price": 20.0}
|
253
|
-
]
|
254
|
-
return db
|
255
|
-
|
256
|
-
@pytest.fixture
|
257
|
-
def app_client(registry):
|
258
|
-
"""Создает тестовый клиент для FastAPI с Command Registry."""
|
259
|
-
from fastapi import FastAPI
|
260
|
-
from command_registry.adapters import RESTAdapter
|
261
|
-
|
262
|
-
app = FastAPI()
|
263
|
-
adapter = RESTAdapter(registry)
|
264
|
-
adapter.register_endpoints(app)
|
265
|
-
|
266
|
-
from fastapi.testclient import TestClient
|
267
|
-
return TestClient(app)
|
268
|
-
```
|
269
|
-
|
270
|
-
## Мокирование внешних зависимостей
|
271
|
-
|
272
|
-
```python
|
273
|
-
import pytest
|
274
|
-
from unittest.mock import patch, MagicMock
|
275
|
-
import requests
|
276
|
-
from myapp.commands.external_commands import fetch_external_data
|
277
|
-
|
278
|
-
@patch("myapp.commands.external_commands.requests.get")
|
279
|
-
def test_fetch_external_data(mock_get):
|
280
|
-
# Настраиваем мок для requests.get
|
281
|
-
mock_response = MagicMock()
|
282
|
-
mock_response.status_code = 200
|
283
|
-
mock_response.json.return_value = {"data": "test_data"}
|
284
|
-
mock_get.return_value = mock_response
|
285
|
-
|
286
|
-
# Вызываем команду
|
287
|
-
result = fetch_external_data("https://api.example.com/data")
|
288
|
-
|
289
|
-
# Проверяем результат
|
290
|
-
assert result == {"data": "test_data"}
|
291
|
-
|
292
|
-
# Проверяем, что запрос был отправлен по правильному URL
|
293
|
-
mock_get.assert_called_once_with("https://api.example.com/data")
|
294
|
-
|
295
|
-
@patch("myapp.commands.external_commands.requests.get")
|
296
|
-
def test_fetch_external_data_error(mock_get):
|
297
|
-
# Настраиваем мок для имитации ошибки
|
298
|
-
mock_response = MagicMock()
|
299
|
-
mock_response.status_code = 404
|
300
|
-
mock_get.return_value = mock_response
|
301
|
-
|
302
|
-
# Проверяем, что команда корректно обрабатывает ошибку
|
303
|
-
with pytest.raises(ValueError, match="Failed to fetch data"):
|
304
|
-
fetch_external_data("https://api.example.com/data")
|
305
|
-
```
|
306
|
-
|
307
|
-
## Тестирование полной интеграции с Command Registry
|
308
|
-
|
309
|
-
```python
|
310
|
-
def test_full_registry_integration(registry):
|
311
|
-
"""
|
312
|
-
Тестирует полную интеграцию с Command Registry, включая:
|
313
|
-
- регистрацию команд
|
314
|
-
- получение метаданных
|
315
|
-
- выполнение команд
|
316
|
-
- обработку ошибок
|
317
|
-
"""
|
318
|
-
# Проверка регистрации
|
319
|
-
commands = registry.get_valid_commands()
|
320
|
-
assert "add_user" in commands
|
321
|
-
assert "get_user" in commands
|
322
|
-
|
323
|
-
# Проверка метаданных
|
324
|
-
add_user_info = registry.get_command_info("add_user")
|
325
|
-
assert add_user_info["description"] == "Создает нового пользователя"
|
326
|
-
assert "name" in add_user_info["params"]
|
327
|
-
assert add_user_info["params"]["name"]["required"] is True
|
328
|
-
|
329
|
-
# Выполнение команды
|
330
|
-
with patch("myapp.commands.user_commands.get_database") as mock_get_db:
|
331
|
-
db_mock = MagicMock()
|
332
|
-
mock_get_db.return_value = db_mock
|
333
|
-
db_mock.users.insert_one.return_value.inserted_id = "new_user_id"
|
334
|
-
|
335
|
-
result = registry.execute("add_user", {
|
336
|
-
"name": "New User",
|
337
|
-
"email": "new@example.com"
|
338
|
-
})
|
339
|
-
|
340
|
-
assert result["id"] == "new_user_id"
|
341
|
-
assert result["name"] == "New User"
|
342
|
-
db_mock.users.insert_one.assert_called_once()
|
343
|
-
|
344
|
-
# Проверка обработки ошибок при выполнении
|
345
|
-
with pytest.raises(ValueError):
|
346
|
-
registry.execute("add_user", {
|
347
|
-
"name": "", # Пустое имя должно вызвать ошибку валидации
|
348
|
-
"email": "new@example.com"
|
349
|
-
})
|
350
|
-
|
351
|
-
# Проверка обработки несуществующей команды
|
352
|
-
with pytest.raises(ValueError, match="Command 'non_existent' not found"):
|
353
|
-
registry.execute("non_existent", {})
|
354
|
-
```
|
355
|
-
|
356
|
-
## Рекомендации по организации тестов
|
357
|
-
|
358
|
-
1. **Структура директорий** - зеркалируйте структуру исходного кода:
|
359
|
-
```
|
360
|
-
src/
|
361
|
-
commands/
|
362
|
-
user_commands.py
|
363
|
-
product_commands.py
|
364
|
-
tests/
|
365
|
-
commands/
|
366
|
-
test_user_commands.py
|
367
|
-
test_product_commands.py
|
368
|
-
```
|
369
|
-
|
370
|
-
2. **Именование** - используйте понятные имена тестов, отражающие проверяемую функциональность:
|
371
|
-
```python
|
372
|
-
def test_add_user_creates_new_user_with_valid_data():
|
373
|
-
# ...
|
374
|
-
|
375
|
-
def test_add_user_raises_error_when_name_is_empty():
|
376
|
-
# ...
|
377
|
-
```
|
378
|
-
|
379
|
-
3. **Документирование тестов** - добавляйте docstrings, поясняющие цель теста:
|
380
|
-
```python
|
381
|
-
def test_calculate_total_applies_discount_correctly():
|
382
|
-
"""
|
383
|
-
Проверяет, что команда calculate_total правильно применяет скидку к сумме.
|
384
|
-
Должна вычесть процент скидки из общей суммы всех цен.
|
385
|
-
"""
|
386
|
-
# ...
|
387
|
-
```
|
388
|
-
|
389
|
-
## Примеры тестирования распространенных сценариев
|
390
|
-
|
391
|
-
### Тестирование команды с транзакцией базы данных
|
392
|
-
|
393
|
-
```python
|
394
|
-
import pytest
|
395
|
-
from unittest.mock import MagicMock, patch
|
396
|
-
from myapp.commands.order_commands import create_order
|
397
|
-
|
398
|
-
@patch("myapp.commands.order_commands.get_database")
|
399
|
-
def test_create_order_transaction(mock_get_db):
|
400
|
-
# Настраиваем моки для базы данных и транзакции
|
401
|
-
db_mock = MagicMock()
|
402
|
-
transaction_mock = MagicMock()
|
403
|
-
db_mock.begin_transaction.return_value = transaction_mock
|
404
|
-
mock_get_db.return_value = db_mock
|
405
|
-
|
406
|
-
# Выполняем команду
|
407
|
-
result = create_order(
|
408
|
-
user_id="user123",
|
409
|
-
items=[
|
410
|
-
{"product_id": "prod1", "quantity": 2},
|
411
|
-
{"product_id": "prod2", "quantity": 1}
|
412
|
-
]
|
413
|
-
)
|
414
|
-
|
415
|
-
# Проверяем, что транзакция была начата и закоммичена
|
416
|
-
db_mock.begin_transaction.assert_called_once()
|
417
|
-
transaction_mock.commit.assert_called_once()
|
418
|
-
|
419
|
-
# Проверяем, что не было отката транзакции
|
420
|
-
transaction_mock.rollback.assert_not_called()
|
421
|
-
|
422
|
-
@patch("myapp.commands.order_commands.get_database")
|
423
|
-
def test_create_order_transaction_rollback(mock_get_db):
|
424
|
-
# Настраиваем моки для имитации ошибки
|
425
|
-
db_mock = MagicMock()
|
426
|
-
transaction_mock = MagicMock()
|
427
|
-
db_mock.begin_transaction.return_value = transaction_mock
|
428
|
-
db_mock.orders.insert_one.side_effect = Exception("DB Error")
|
429
|
-
mock_get_db.return_value = db_mock
|
430
|
-
|
431
|
-
# Проверяем, что команда корректно обрабатывает ошибку
|
432
|
-
with pytest.raises(Exception):
|
433
|
-
create_order(
|
434
|
-
user_id="user123",
|
435
|
-
items=[{"product_id": "prod1", "quantity": 2}]
|
436
|
-
)
|
437
|
-
|
438
|
-
# Проверяем, что транзакция была начата и откачена
|
439
|
-
db_mock.begin_transaction.assert_called_once()
|
440
|
-
transaction_mock.rollback.assert_called_once()
|
441
|
-
```
|
442
|
-
|
443
|
-
### Тестирование логирования в командах
|
444
|
-
|
445
|
-
```python
|
446
|
-
import pytest
|
447
|
-
import logging
|
448
|
-
from unittest.mock import patch
|
449
|
-
from myapp.commands.user_commands import delete_user
|
450
|
-
|
451
|
-
@patch("myapp.commands.user_commands.logger")
|
452
|
-
@patch("myapp.commands.user_commands.get_database")
|
453
|
-
def test_delete_user_logging(mock_get_db, mock_logger):
|
454
|
-
# Настраиваем мок базы данных
|
455
|
-
db_mock = MagicMock()
|
456
|
-
db_mock.users.delete_one.return_value.deleted_count = 1
|
457
|
-
mock_get_db.return_value = db_mock
|
458
|
-
|
459
|
-
# Выполняем команду
|
460
|
-
result = delete_user("user123")
|
461
|
-
|
462
|
-
# Проверяем, что логи были созданы
|
463
|
-
mock_logger.info.assert_any_call("Deleting user with ID: user123")
|
464
|
-
mock_logger.info.assert_any_call("User user123 successfully deleted")
|
465
|
-
```
|
466
|
-
|
467
|
-
## Заключение
|
468
|
-
|
469
|
-
Тестирование команд в Command Registry - важная часть обеспечения качества приложения. Используйте комбинацию модульных, интеграционных и E2E тестов для достижения максимального покрытия. Помните, что хорошие тесты не только проверяют правильную работу кода, но и документируют ожидаемое поведение системы.
|