Руководство по SDK
Mockarty предоставляет официальные SDK-библиотеки для Go, Python, Java и Kotlin. Все SDK обеспечивают типобезопасный доступ к API Mockarty для управления моками, тестирования, фаззинга, контрактного тестирования, нагрузочного тестирования и многого другого.
Все SDK следуют единым принципам проектирования: fluent-билдеры для создания моков, согласованные имена API между языками, настройка через переменные окружения и встроенная интеграция с тестовыми фреймворками.
URL-адреса в примерах: Во всех примерах используется
localhost:5770как адрес Mockarty по умолчанию. Если ваш экземпляр работает на удалённом сервере, заменитеlocalhost:5770на реальный адрес (например,https://mockarty.company.comилиhttp://192.168.1.50:5770). Подробнее — в разделе Полезные функции и советы.
Прогон системы под тестом: помимо настройки mock’ов SDK предоставляют тестовые клиенты для gRPC, Kafka, RabbitMQ, SOAP, GraphQL, SSE, WebSocket с автоматическим step-capture в external-прогоны TCM. См. Протокольные клиенты SDK — кросс-языковой справочник.
Поддерживаемые языки
| Язык | Пакет | GitHub | Статус |
|---|---|---|---|
| Go | github.com/mockarty/mockarty-go |
github.com/mockarty/mockarty-go | Стабильный |
| Python | mockarty (PyPI) |
github.com/mockarty/py-sdk | Стабильный |
| Java | ru.mockarty:mockarty-java (Maven Central) |
github.com/mockarty/java-sdk | Стабильный |
| Kotlin | ru.mockarty:mockarty-kotlin (Maven Central) |
github.com/mockarty/java-sdk | Стабильный |
Установка
Go
go get github.com/mockarty/mockarty-go
Требования: Go 1.21+, без внешних зависимостей (только стандартная библиотека).
Python
# pip
pip install mockarty
# Poetry
poetry add mockarty
# С поддержкой async HTTP/2
pip install mockarty[async]
Требования: Python 3.9+.
Java (Maven)
<dependency>
<groupId>ru.mockarty</groupId>
<artifactId>mockarty-java</artifactId>
<version>1.0.0</version>
</dependency>
<!-- Расширение JUnit 5 (тестовая область) -->
<dependency>
<groupId>ru.mockarty</groupId>
<artifactId>mockarty-junit5</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
Java (Gradle)
// Основной SDK
implementation("ru.mockarty:mockarty-java:1.0.0")
// Расширение JUnit 5
testImplementation("ru.mockarty:mockarty-junit5:1.0.0")
Kotlin
implementation("ru.mockarty:mockarty-kotlin:1.0.0")
Предоставляет Kotlin DSL расширения поверх Java SDK.
Настройка клиента
Go
import mockarty "github.com/mockarty/mockarty-go"
client := mockarty.NewClient("http://localhost:5770",
mockarty.WithAPIKey("mk_your_api_key"), // Аутентификация по API-ключу
mockarty.WithNamespace("production"), // Пространство имён (по умолчанию: "sandbox")
mockarty.WithTimeout(10 * time.Second), // Таймаут HTTP (по умолчанию: 30с)
mockarty.WithRetry(3, time.Second), // Повторные попытки с экспоненциальной задержкой
mockarty.WithHTTPClient(customClient), // Пользовательский http.Client
mockarty.WithLogger(slog.Default()), // Структурированный логгер
)
Python
from mockarty import MockartyClient, AsyncMockartyClient
# Синхронный клиент
client = MockartyClient(
base_url="http://localhost:5770",
api_key="mk_your_api_key",
namespace="sandbox",
timeout=30,
max_retries=3,
)
# Асинхронный клиент (требует mockarty[async])
async_client = AsyncMockartyClient(
base_url="http://localhost:5770",
api_key="mk_your_api_key",
)
# Поддержка контекстного менеджера
with MockartyClient() as client:
client.mocks.create(mock)
# client.close() вызывается автоматически
# Асинхронный контекстный менеджер
async with AsyncMockartyClient() as client:
await client.mocks.create(mock)
Java
import ru.mockarty.MockartyClient;
// Паттерн Builder, поддержка AutoCloseable
try (MockartyClient client = MockartyClient.builder()
.baseUrl("http://localhost:5770")
.apiKey("mk_your_api_key")
.namespace("sandbox")
.timeout(Duration.ofSeconds(30))
.build()) {
client.mocks().create(mock);
}
Kotlin
import ru.mockarty.MockartyClient
// Сокращённая фабрика
val client = MockartyClient.create("http://localhost:5770", "mk_your_api_key")
Переменные окружения
Все SDK поддерживают настройку через переменные окружения:
| Переменная | Описание | По умолчанию |
|---|---|---|
MOCKARTY_BASE_URL |
URL сервера Mockarty | http://localhost:5770 |
MOCKARTY_API_KEY |
Ключ аутентификации API | (нет) |
MOCKARTY_NAMESPACE |
Пространство имён по умолчанию | sandbox |
Справочник API
API моков
Создание, чтение, обновление и удаление моков. Поддержка пакетных операций, мягкого удаления/восстановления, версионирования и доступа к логам.
Go
// Создание
resp, err := client.Mocks().Create(ctx, mock)
// Получение / Список
mock, err := client.Mocks().Get(ctx, "mock-id")
list, err := client.Mocks().List(ctx, &mockarty.ListMocksOptions{
Namespace: "production",
Tags: []string{"users"},
Limit: 20,
})
// Обновление / Удаление / Восстановление / Полное удаление
updated, err := client.Mocks().Update(ctx, "mock-id", mock)
err = client.Mocks().Delete(ctx, "mock-id")
err = client.Mocks().Restore(ctx, "mock-id")
err = client.Mocks().Purge(ctx, "mock-id")
// Пакетные операции
err = client.Mocks().BatchCreate(ctx, mocks)
err = client.Mocks().BatchDelete(ctx, ids)
err = client.Mocks().BatchRestore(ctx, ids)
// Логи и версии
logs, err := client.Mocks().Logs(ctx, "mock-id", &mockarty.LogsOptions{Limit: 50})
versions, err := client.Mocks().Versions(ctx, "chain-id")
Python
# Создание
result = client.mocks.create(mock)
# Получение / Список
mock = client.mocks.get("mock-id")
page = client.mocks.list(namespace="sandbox", limit=10)
for m in page.items:
print(m.id)
# Удаление / Восстановление
client.mocks.delete("mock-id")
client.mocks.restore("mock-id")
Java
// Создание
client.mocks().create(mock);
// Получение / Список
Mock mock = client.mocks().get("mock-id");
// Удаление / Восстановление
client.mocks().delete("mock-id");
client.mocks().restore("mock-id");
API хранилищ
Доступ к глобальным и цепочечным хранилищам для сценариев с состоянием.
Go
// Глобальное хранилище
store, err := client.Stores().GlobalGet(ctx)
err = client.Stores().GlobalSet(ctx, "counter", 42)
err = client.Stores().GlobalDelete(ctx, "key1")
err = client.Stores().GlobalDeleteMany(ctx, "key1", "key2")
// Цепочечное хранилище
store, err := client.Stores().ChainGet(ctx, "chain-id")
err = client.Stores().ChainSet(ctx, "chain-id", "status", "completed")
err = client.Stores().ChainDelete(ctx, "chain-id", "key")
err = client.Stores().ChainDeleteMany(ctx, "chain-id", "key1", "key2")
Python
# Глобальное хранилище
client.stores.global_set("counter", 0)
data = client.stores.global_get()
# Цепочечное хранилище
client.stores.chain_set("order-flow", "orderId", "abc-123")
chain_data = client.stores.chain_get("order-flow")
Java
// Глобальное хранилище
client.stores().globalSet("counter", 0);
Map<String, Object> store = client.stores().globalGet();
// Цепочечное хранилище
client.stores().chainSet("registration-flow", "step", "1");
API пространств имён
Создание и получение списка пространств имён для изоляции моков.
Go
err := client.Namespaces().Create(ctx, "production")
namespaces, err := client.Namespaces().List(ctx)
Python
client.namespaces.create("production")
namespaces = client.namespaces.list()
Java
client.namespaces().create("production");
API коллекций и тестовых запусков
Запуск коллекций API-тестов и получение результатов.
Go
collections, err := client.Collections().List(ctx)
result, err := client.Collections().Execute(ctx, "collection-id")
Python
collections = client.collections.list()
result = client.collections.execute("collection-id")
Java
client.collections().list();
client.collections().execute("collection-id");
API нагрузочного тестирования
Запуск нагрузочных тестов, управление конфигурациями и расписаниями, сравнение результатов.
Go
task, err := client.Perf().Run(ctx, &mockarty.PerfConfig{...})
err = client.Perf().Stop(ctx, "task-id")
results, err := client.Perf().Results(ctx)
Python
task = client.perf.run(config)
client.perf.stop("task-id")
results = client.perf.results()
Java
client.perf().run(config);
client.perf().stop("task-id");
client.perf().results();
API фаззинга
Запуск сессий фаззинга безопасности, управление конфигурациями и триаж находок.
Go
task, err := client.Fuzzing().Start(ctx, &mockarty.FuzzConfig{...})
findings, err := client.Fuzzing().ListFindings(ctx)
Python
task = client.fuzzing.start(config)
findings = client.fuzzing.list_findings()
Java
client.fuzzing().start(config);
client.fuzzing().listFindings();
API контрактного тестирования
Валидация моков по API-спецификациям, верификация провайдеров, управление Pact-контрактами, проверки can-i-deploy и использование реестра API для управления контрактами между командами.
Go
// Валидация моков по OpenAPI/Swagger-спецификации
result, err := client.Contracts().ValidateMocks(ctx, &mockarty.ContractValidationRequest{
SpecURL: "https://petstore.swagger.io/v2/swagger.json",
Namespace: "production",
})
// Верификация живого провайдера по контракту
verify, err := client.Contracts().VerifyProvider(ctx, &mockarty.ContractValidationRequest{
SpecURL: "https://api.example.com/openapi.json",
TargetURL: "https://api.example.com",
})
// Поддержка Pact
pacts, err := client.Contracts().ListPacts(ctx)
published, err := client.Contracts().PublishPact(ctx, &mockarty.Pact{
Consumer: "frontend",
Provider: "user-service",
Spec: pactJSON,
})
deploy, err := client.Contracts().CanIDeploy(ctx, canIDeployReq)
mocks, err := client.Contracts().GenerateMocksFromPact(ctx, "pact-id")
// Обнаружение дрейфа между контрактом и живым сервисом
drift, err := client.Contracts().DetectDrift(ctx, driftReq)
// Реестр API: публикация, подписка, проверка ломающих изменений
entries, err := client.Contracts().ListRegistry(ctx, "")
entry, err := client.Contracts().PublishToRegistry(ctx, &mockarty.RegistryEntry{
ServiceName: "user-service",
SpecType: "openapi",
Version: "2.0.0",
})
sub, err := client.Contracts().Subscribe(ctx, "entry-id", &mockarty.Subscription{
ServiceName: "frontend",
NotifyOnBreaking: true,
})
impact, err := client.Contracts().CheckImpact(ctx, "entry-id", newSpecContent)
// Конфиги и результаты
configs, err := client.Contracts().ListConfigs(ctx)
results, err := client.Contracts().ListResults(ctx)
Python
result = client.contracts.validate_mocks({"specUrl": "...", "namespace": "production"})
pacts = client.contracts.list_pacts()
deploy = client.contracts.can_i_deploy(request)
entries = client.contracts.list_registry()
Java
client.contracts().validateMocks(request);
client.contracts().listPacts();
client.contracts().canIDeploy(request);
client.contracts().listRegistry("");
API записи трафика
Захват живого трафика и генерация моков из записанных запросов.
Go
// Запуск сессии записи
session, err := client.Recorder().StartRecording(ctx, &mockarty.RecorderSession{
Name: "capture-login-flow",
TargetURL: "https://api.example.com",
})
// Управление сессиями
sessions, err := client.Recorder().ListSessions(ctx)
session, err = client.Recorder().GetSession(ctx, "session-id")
err = client.Recorder().StopRecording(ctx, "session-id")
err = client.Recorder().RestartRecording(ctx, "session-id")
// Работа с записанными запросами
entries, err := client.Recorder().GetEntries(ctx, "session-id")
err = client.Recorder().AnnotateEntry(ctx, "session-id", "entry-id", annotation)
err = client.Recorder().ReplayEntry(ctx, "session-id", "entry-id")
// Генерация моков из записанного трафика
mocks, err := client.Recorder().CreateMocksFromSession(ctx, "session-id", nil)
// Экспорт сессии как HAR
har, err := client.Recorder().ExportSession(ctx, "session-id")
// Управление CA-сертификатом (для записи HTTPS)
caStatus, err := client.Recorder().GetCAStatus(ctx)
err = client.Recorder().GenerateCA(ctx)
caCert, err := client.Recorder().DownloadCA(ctx)
Python
session = client.recorder.create(config)
sessions = client.recorder.list()
session = client.recorder.get("session-id")
client.recorder.stop("session-id")
entries = client.recorder.entries("session-id")
mocks = client.recorder.generate_mocks("session-id")
Java
RecorderSession s = client.recorder().start(config);
client.recorder().listSessions();
client.recorder().getSession("session-id");
client.recorder().stopRecording("session-id");
client.recorder().getEntries("session-id");
client.recorder().createMocks("session-id", null);
API здоровья
Проверка состояния сервера, liveness и readiness пробы.
Go
health, err := client.Health().Check(ctx)
err = client.Health().Live(ctx)
err = client.Health().Ready(ctx)
Python
health = client.health.check()
print(health.status)
Java
boolean healthy = client.health().ready();
API хаос-инженерии
BETA — Управляемые эксперименты по внедрению отказов в Kubernetes-кластерах. Подробнее в руководстве по хаос-инженерии.
Go
// Профили кластеров (подключение к Kubernetes)
profiles, err := client.Chaos().ListProfiles(ctx)
profile, err := client.Chaos().CreateProfile(ctx, &mockarty.ChaosProfile{
Name: "staging-cluster",
KubeconfigData: base64Kubeconfig,
Context: "staging-ctx",
})
connResult, err := client.Chaos().TestProfile(ctx, profile.ID)
// Список пресетов (готовые шаблоны экспериментов)
presets, err := client.Chaos().ListPresets(ctx)
// Создание и запуск эксперимента
exp, err := client.Chaos().Create(ctx, &mockarty.ChaosExperiment{
Name: "pod-kill-test",
Namespace: "staging",
DurationSec: 300,
Faults: []mockarty.FaultConfig{{
Type: mockarty.FaultPodKillRandom,
GracePeriodSec: 5,
}},
Target: mockarty.TargetConfig{
Mode: mockarty.TargetModeAll,
Selector: map[string]string{"app": "frontend"},
},
Safety: mockarty.SafetyConfig{
MinReplicasAlive: 1,
AutoRollback: true,
},
})
err = client.Chaos().Run(ctx, exp.ID)
// Мониторинг эксперимента
metrics, err := client.Chaos().GetMetrics(ctx, exp.ID)
events, err := client.Chaos().GetEvents(ctx, exp.ID)
err = client.Chaos().Abort(ctx, exp.ID) // экстренная остановка
// Получение отчёта и скачивание
report, err := client.Chaos().GetReport(ctx, exp.ID)
htmlReport, err := client.Chaos().DownloadReport(ctx, exp.ID, "html")
// Операции с кластером (ad-hoc)
topology, err := client.Chaos().GetTopology(ctx, profile.ID, "default")
err = client.Chaos().KillPod(ctx, "staging", "frontend-abc123", 0)
podDetail, err := client.Chaos().GetPodDetail(ctx, "staging", "frontend-abc123")
logs, err := client.Chaos().GetPodLogs(ctx, "staging", "frontend-abc123", "app", 100)
result, err := client.Chaos().ScaleDeployment(ctx, "staging", "frontend", 3)
// Управление оператором
opStatus, err := client.Chaos().GetOperatorStatus(ctx, "chaos-system")
manifest, err := client.Chaos().GenerateOperatorManifest(ctx, "https://mockarty.example.com", "")
Python
# Список пресетов
presets = client.chaos.list_presets()
# Создание и запуск эксперимента
exp = client.chaos.create({
"name": "pod-kill-test",
"namespace": "staging",
"durationSec": 300,
"faults": [{"type": "pod_kill_random"}],
"target": {"mode": "all", "selector": {"app": "frontend"}},
"safety": {"minReplicasAlive": 1, "autoRollback": True},
})
client.chaos.run(exp["id"])
# Получение отчёта
report = client.chaos.get_report(exp["id"])
Java
// Создание и запуск эксперимента
ChaosExperiment exp = client.chaos().create(new ChaosExperiment()
.setName("pod-kill-test")
.setNamespace("staging")
.setDurationSec(300));
client.chaos().run(exp.getId());
// Получение отчёта
Map<String, Object> report = client.chaos().getReport(exp.getId());
Билдер моков (Fluent API)
Все SDK предоставляют fluent-билдер для конструирования моков с полной типобезопасностью.
HTTP-мок с условиями
Go
mock := mockarty.NewMockBuilder().
ID("create-order").
HTTP(func(h *mockarty.HTTPBuilder) {
h.Route("/api/orders").
Method("POST").
HeaderCondition("Authorization", mockarty.AssertNotEmpty, nil)
}).
Response(func(r *mockarty.ResponseBuilder) {
r.Status(201).
Header("Content-Type", "application/json").
JSONBody(map[string]any{
"orderId": "$.fake.UUID",
"amount": "$.req.amount",
"status": "created",
})
}).
Build()
Python
from mockarty import MockBuilder, AssertAction
mock = (
MockBuilder.http("/api/orders", "POST")
.id("create-order")
.namespace("production")
.tags("orders", "v2")
.priority(10)
.condition("$.body.amount", AssertAction.NOT_EMPTY)
.header_condition("Authorization", AssertAction.NOT_EMPTY)
.respond(201, body={
"orderId": "$.fake.UUID",
"amount": "$.req.amount",
"status": "created",
})
.callback("https://webhook.site/test", method="POST", body={"event": "order.created"})
.ttl(7200)
.build()
)
Java
import ru.mockarty.builder.MockBuilder;
import ru.mockarty.model.AssertAction;
Mock mock = MockBuilder.http("/api/orders", "POST")
.id("create-order")
.condition("$.body.amount", AssertAction.NOT_EMPTY, null)
.headerCondition("Authorization", AssertAction.NOT_EMPTY, null)
.queryCondition("format", AssertAction.EQUALS, "json")
.respond(201, Map.of(
"orderId", "$.fake.UUID",
"amount", "$.req.amount",
"status", "created"
))
.callback("https://webhook.example.com/notify", "POST",
Map.of("event", "order.created"))
.ttl(3600)
.build();
Kotlin
import ru.mockarty.dsl.*
import ru.mockarty.model.AssertAction
client.createMock {
id = "create-order"
namespace = "production"
tags = listOf("orders", "v2")
http {
route = "/api/orders"
method = "POST"
headerCondition("Authorization", AssertAction.NOT_EMPTY)
}
respond {
statusCode = 201
body = mapOf(
"orderId" to "$.fake.UUID",
"amount" to "$.req.amount",
"status" to "created"
)
}
ttl = 3600
}
gRPC-мок
Go
mock := mockarty.NewMockBuilder().
ID("grpc-user").
GRPC(func(g *mockarty.GRPCBuilder) {
g.Service("UserService").Method("GetUser")
}).
Response(func(r *mockarty.ResponseBuilder) {
r.JSONBody(map[string]any{"name": "John", "email": "john@test.com"})
}).
Build()
Python
grpc_mock = (
MockBuilder.grpc("user.UserService", "GetUser")
.id("grpc-get-user")
.condition("$.id", AssertAction.NOT_EMPTY)
.respond(200, body={"id": "$.req.id", "name": "$.fake.FirstName"})
.build()
)
Java
Mock mock = MockBuilder.grpc("UserService", "GetUser")
.serverName("grpc-server")
.condition("$.user_id", AssertAction.EQUALS, "123")
.respond(200, Map.of("name", "John", "email", "john@test.com"))
.build();
MCP-мок
Go
mock := mockarty.NewMockBuilder().
ID("mcp-weather").
MCPConfig(func(m *mockarty.MCPBuilderCtx) {
m.Tool("get_weather")
}).
Response(func(r *mockarty.ResponseBuilder) {
r.JSONBody(map[string]any{"temperature": 22, "city": "$.req.city"})
}).
Build()
Python
mcp_mock = (
MockBuilder.mcp("get_weather")
.id("mcp-weather")
.respond(200, body={"temperature": 22, "city": "$.req.city"})
.build()
)
Java
Mock mock = MockBuilder.mcp("search_documents")
.condition("$.query", AssertAction.NOT_EMPTY, null)
.respond(200, Map.of("results", List.of("doc1", "doc2")))
.build();
Прокси и OneOf
Go
// Прокси на реальный бэкенд
proxy := mockarty.NewMockBuilder().
ID("proxy").
HTTP(func(h *mockarty.HTTPBuilder) {
h.Route("/api/external").Method("GET")
}).
ProxyTo("https://real-api.example.com").
Build()
// OneOf ответы (случайные или последовательные)
flaky := mockarty.NewMockBuilder().
ID("flaky-service").
HTTP(func(h *mockarty.HTTPBuilder) {
h.Route("/api/data").Method("GET")
}).
OneOfConfig(mockarty.OneOfOrderRandom,
func(r *mockarty.ResponseBuilder) { r.Status(200).JSONBody("ok") },
func(r *mockarty.ResponseBuilder) { r.Status(500).Error("boom") },
).
Build()
Python
# Прокси
proxy = (
MockBuilder.http("/api/external", "GET")
.id("proxy")
.proxy_to("https://real-api.example.com")
.build()
)
Java
// Прокси
Mock proxy = MockBuilder.http("/api/real-service", "GET")
.proxyTo("https://api.example.com")
.build();
// OneOf ответы (по порядку)
Mock flaky = MockBuilder.http("/api/flaky", "GET")
.oneOfOrdered(
new ContentResponse().statusCode(200).payload(Map.of("status", "ok")),
new ContentResponse().statusCode(500).error("server error"),
new ContentResponse().statusCode(200).payload(Map.of("status", "recovered"))
)
.build();
Обработка ошибок
REST API Mockarty возвращает единый JSON-конверт для каждой ошибки 4xx/5xx:
{
"error": "безопасное человекочитаемое сообщение",
"code": "not_found",
"request_id": "8c3a…d12"
}
error— безопасное сообщение, никогда не содержит SQL-строк, стек-трейсов
или путей. Можно показывать пользователю напрямую.code— стабильный машинный идентификатор из закрытого набора
(validation,unauthorized,forbidden,not_found,conflict,
rate_limit,unavailable,external,internal). Используйте именно
его для ветвления в коде, а не текст сообщения.request_id— серверный correlation ID. Указывайте его в обращениях
поддержки — оператор найдёт нужную запись в логах.
Каждый SDK разбирает конверт и выбрасывает типизированные исключения /
sentinel ошибки, соответствующие полю code. Старые серверы могут
возвращать только error — SDK и CLI в этом случае откатываются на
маршрутизацию по HTTP-статусу.
Go
import "errors"
_, err := client.Mocks().Get(ctx, "nonexistent")
if errors.Is(err, mockarty.ErrNotFound) {
// Работает и с новым (code="not_found"), и со старым сервером.
}
var apiErr *mockarty.APIError
if errors.As(err, &apiErr) {
fmt.Printf("status=%d code=%q msg=%q request_id=%q\n",
apiErr.StatusCode, apiErr.Code, apiErr.Message, apiErr.RequestID)
}
Python
from mockarty.errors import MockartyNotFoundError, MockartyAPIError
try:
mock = client.mocks.get("non-existent")
except MockartyNotFoundError as e:
print(f"мок не найден (request_id={e.request_id})")
except MockartyAPIError as e:
# e.code — стабильный kind ("validation", "rate_limit", ...).
# e.request_id — серверный correlation ID.
print(f"status={e.status_code} code={e.code} msg={e.message} request_id={e.request_id}")
Java
import ru.mockarty.exception.MockartyException;
import ru.mockarty.exception.MockartyNotFoundException;
try {
client.mocks().get("non-existent");
} catch (MockartyNotFoundException e) {
System.out.println("Мок не найден");
} catch (MockartyException e) {
System.out.printf("Ошибка API %d: %s%n", e.getStatusCode(), e.getMessage());
}
Интеграция с тестами
Go: Тестовые хелперы
Go SDK предоставляет методы-хелперы *T, которые автоматически очищают ресурсы по завершении теста:
func TestUserAPI(t *testing.T) {
client := mockarty.NewClient("http://localhost:5770",
mockarty.WithAPIKey("mk_test_key"),
)
// Создание пространства имён с авто-очисткой
client.SetupNamespaceT(t, "test-ns")
// Создание мока с авто-очисткой
mock := client.CreateMockT(t, mockarty.NewMockBuilder().
ID("test-user-get").
Namespace("test-ns").
HTTP(func(h *mockarty.HTTPBuilder) {
h.Route("/api/users/1").Method("GET")
}).
Response(func(r *mockarty.ResponseBuilder) {
r.Status(200).JSONBody(map[string]any{"id": "1", "name": "Test"})
}).
Build(),
)
// мок автоматически удаляется по завершении теста
_ = mock
}
Python: pytest-фикстуры
pip install mockarty[test]
# conftest.py
pytest_plugins = ["mockarty.testing.fixtures"]
# test_example.py
def test_create_mock(mock_cleanup):
from mockarty import MockBuilder
mock = MockBuilder.http("/test", "GET").respond(200, body="ok").build()
created = mock_cleanup(mock)
assert created.id is not None
Java: Расширение JUnit 5
import ru.mockarty.junit5.MockartyTest;
import ru.mockarty.junit5.MockartyServer;
import ru.mockarty.MockartyClient;
import ru.mockarty.builder.MockBuilder;
@MockartyTest(namespace = "test", cleanupAfterEach = true)
class UserApiTest {
@Test
void shouldReturnUser(MockartyClient client, MockartyServer server) {
server.createMock(MockBuilder.http("/api/users/1", "GET")
.respond(200, Map.of("id", 1, "name", "John"))
.build());
// Ваш тестовый код...
// Моки автоматически очищаются после каждого теста
}
}
Kotlin: DSL в тестах
@MockartyTest(namespace = "test", cleanupAfterEach = true)
class UserApiTest {
@Test
fun `should return user`(client: MockartyClient) {
client.createMock {
id = "test-user"
http {
route = "/api/users/1"
method = "GET"
}
respond {
statusCode = 200
body = mapOf("id" to 1, "name" to "John")
}
}
// Проверки здесь...
}
}
Лучшие практики
-
Используйте пространства имён для изоляции. Каждый набор тестов или окружение должны использовать собственное пространство имён, чтобы избежать конфликтов моков.
-
Устанавливайте TTL для тестовых моков. Всегда устанавливайте
ttlдля моков, созданных при тестировании, чтобы они автоматически удалялись, даже если teardown не выполнился. -
Используйте билдер моков для типобезопасности. Fluent API билдера отлавливает ошибки на этапе компиляции (или в IDE), а не во время выполнения.
-
Очищайте моки после тестов. Используйте встроенные тестовые хелперы (
SetupNamespaceTв Go,mock_cleanupв Python,@MockartyTestв Java/Kotlin) для автоматической очистки. -
Используйте хранилища для сценариев с состоянием. Цепочечные хранилища позволяют моделировать многоэтапные процессы (например, создание заказа -> оплата -> доставка) с передачей состояния между вызовами моков.
-
Предпочитайте переменные окружения для CI/CD. Устанавливайте
MOCKARTY_BASE_URLиMOCKARTY_API_KEYв окружении пайплайна вместо жёсткого кодирования значений. -
Используйте пакетные операции для настройки. При создании нескольких моков для тестового сценария используйте
BatchCreateдля сокращения HTTP-запросов. -
Версионируйте ваши моки. Используйте API версионирования для отслеживания изменений моков и отката при необходимости.
Устранение проблем
| Ошибка | Причина | Решение |
|---|---|---|
MockartyConnectionError / connection refused |
Сервер Mockarty не запущен или base_url указывает на неверный хост/порт |
Проверьте, что curl $MOCKARTY_BASE_URL/health возвращает ok |
MockartyUnauthorizedError (401) |
Отсутствует или неверный API-токен | Создайте токен в разделе Админка → API-токены и задайте MOCKARTY_API_KEY |
MockartyForbiddenError (403) с invalid license |
На сервере не активирована лицензия | Активируйте лицензионный ключ в Администрировании → Лицензия или обратитесь к администратору |
MockartyForbiddenError (403) на namespace |
Токен ограничен другим пространством имён | Используйте токен с доступом к нужному пространству или переключите его в клиенте |
MockartyConflictError (409) при create |
Мок с таким ID уже существует | Используйте upsert/update или сгенерируйте уникальный ID |
MockartyNotFoundError при разрешении |
Мок существует, но namespace/route/method не совпадают | Проверьте поля мока через list или UI; обратите внимание на слеши и регистр метода |
| Плейсхолдеры Faker видны в ответе как обычная строка | payload отправлен как строка, а не как шаблонный объект |
Передайте dict/Map со значениями "$.fake.*", а не готовую строку |
| Запрос зависает без таймаута | У клиента по умолчанию нет таймаута | Задайте timeout в билдере (например, MockartyClient(timeout=30)) |
| Тесты нестабильно падают при параллельном запуске | Несколько тестов используют одно пространство и одинаковые ID моков | Используйте отдельное пространство на каждый тестовый набор или рандомизируйте ID |
Для специфичных для протокола проблем (gRPC, MCP, Kafka и т. д.) смотрите соответствующий раздел в Справочнике API.
Интеграция с тест-фреймворками
Каждая SDK содержит тонкий framework-слой, который встраивается в ваш
любимый раннер тестов: статус теста, шаги, перехваченные логи и
небольшие вложения автоматически уходят в Mockarty в виде синтетического
case run. Декорируете тест, запускаете — история появляется в UI без
дополнительного клея.
Python — pytest-плагин
После pip install mockarty плагин для pytest подхватится автоматически.
Установите MOCKARTY_BASE_URL и MOCKARTY_API_KEY (или передайте
mockarty_client как фикстуру) и декорируйте нужные тесты:
from mockarty.testing import test_case, attach_report, step, attach
@test_case("CASE-LOGIN-1", plan="qa-smoke")
@attach_report
def test_login(mockarty_client):
with step("submit form"):
...
with step("verify response"):
attach("response.json", response.text, content_type="application/json")
assert response.status_code == 200
@test_case("CASE-ID")привязывает тест к существующему кейсу. С
параметрамиauto_create=Trueиname="..."кейс будет создан при
первом запуске.@attach_reportвключает выгрузку результата.with step("...")записывает TCM-шаг. Шаги вкладываются друг в друга.
Если установленallure-pytest, шаги дублируются в Allure.attach(name, body, content_type=...)добавляет небольшое вложение,
которое будет видно в UI рядом с case run.
Java — JUnit 5 extension
Добавьте mockarty-junit5 в test-зависимости и поставьте @MockartyTest
на класс. Привязка к кейсам — на уровне метода:
@MockartyTest(namespace = "qa")
class LoginTest {
@Test
@TestCase("CASE-LOGIN-1")
@AttachReport
void login(MockartyClient client) {
try (Step s = Step.open("submit form")) {
// ...
}
Step.run("verify", () -> assertEquals(200, response.status()));
}
}
Те же примитивы доступны через Step.open(...) / Step.run(...) и
Attachments.attach(...).
Go — хелперы для testing.T
Go SDK даёт хелперы, которые привязывают *testing.T к namespace
Mockarty и чистят созданные моки при выходе теста. Чтобы запустить
Test Plan из Go-теста и проверить итог:
func TestLoginFlow(t *testing.T) {
c := mockarty.NewClient(os.Getenv("MOCKARTY_BASE_URL"),
mockarty.WithAPIKey(os.Getenv("MOCKARTY_API_KEY")))
c.RunPlanT(t, "qa-smoke") // помечает тест упавшим, если plan-run упал
}
Поведение по умолчанию
Все три framework’а fail-soft: если до сервера Mockarty не достучаться
(нет env, сервер недоступен) — декораторы / аннотации работают как no-op,
и тест выполняется локально. Framework никогда не валит ваш тест
из-за того, что не получилось отчитаться.