SDK Guide
Use a Mockarty SDK when you want to create mocks or run tests from your application code or CI pipeline. Choose Go, Python, Java, or Kotlin below; each has examples for the tasks it supports.
Before you start, you need a running Mockarty server, an API token with access to your namespace, and that namespace’s name. Install your language’s package, configure the client, then try the Mocks API. For a first look at the product itself, start with the Quick Start.
About URLs in examples: All examples use
localhost:5770as the default Mockarty address. If your instance runs on a remote server, replacelocalhost:5770with its actual address (e.g.https://mockarty.company.comorhttp://192.168.1.50:5770). See Tips & Useful Features for details.
Driving the system under test: beyond configuring mocks, the SDKs ship test clients for gRPC, Kafka, RabbitMQ, SOAP, GraphQL, SSE, WebSocket with auto-step capture into TCM external runs. See SDK Protocol Clients for the cross-language reference.
Supported Languages
| Language | Package | GitHub | Status |
|---|---|---|---|
| Go | github.com/mockarty/mockarty-go |
github.com/mockarty/mockarty-go | Stable |
| Python | mockarty (PyPI) |
github.com/mockarty/py-sdk | Beta |
| Java | ru.mockarty:mockarty-java (Maven Central) |
github.com/mockarty/java-sdk | Stable |
| Kotlin | ru.mockarty:mockarty-kotlin (Maven Central) |
github.com/mockarty/java-sdk | Stable |
Installation
Go
go get github.com/mockarty/mockarty-go
Requirements: Go 1.25+. The core client uses only the Go standard library; the optional protocol and testing sub-packages pull their own dependencies.
Python
# pip
pip install mockarty
# Poetry
poetry add mockarty
# Optional HTTP/2 support for the async client
pip install mockarty[async]
Requirements: Python 3.9+.
Java (Maven)
<dependency>
<groupId>ru.mockarty</groupId>
<artifactId>mockarty-java</artifactId>
<version>0.3.0</version>
</dependency>
<!-- JUnit 5 extension (test scope) -->
<dependency>
<groupId>ru.mockarty</groupId>
<artifactId>mockarty-junit5</artifactId>
<version>0.3.0</version>
<scope>test</scope>
</dependency>
Java (Gradle)
// Core SDK
implementation("ru.mockarty:mockarty-java:0.3.0")
// JUnit 5 extension
testImplementation("ru.mockarty:mockarty-junit5:0.3.0")
Kotlin
implementation("ru.mockarty:mockarty-kotlin:0.3.0")
Provides Kotlin DSL extensions on top of the Java SDK.
Client Configuration
Go
import mockarty "github.com/mockarty/mockarty-go"
client := mockarty.NewClient("http://localhost:5770",
mockarty.WithAPIKey("mk_your_api_key"), // API key authentication
mockarty.WithNamespace("production"), // Default namespace (default: "sandbox")
mockarty.WithTimeout(10 * time.Second), // HTTP timeout (default: 30s)
mockarty.WithRetry(3, time.Second), // Retry with exponential back-off
mockarty.WithHTTPClient(customClient), // Custom http.Client
mockarty.WithLogger(slog.Default()), // Structured logger
)
Python
from mockarty import MockartyClient, AsyncMockartyClient
# Synchronous client
client = MockartyClient(
base_url="http://localhost:5770",
api_key="mk_your_api_key",
namespace="sandbox",
timeout=30,
max_retries=3,
)
# Async client (included in the base package)
async_client = AsyncMockartyClient(
base_url="http://localhost:5770",
api_key="mk_your_api_key",
)
# Context manager support
with MockartyClient() as client:
client.mocks.create(mock)
# client.close() is called automatically
# Async context manager
async with AsyncMockartyClient() as client:
await client.mocks.create(mock)
Java
import ru.mockarty.MockartyClient;
// Builder pattern, 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
// Shorthand factory
val client = MockartyClient.create("http://localhost:5770", "mk_your_api_key")
Environment Variables
Environment defaults differ by language. Python and Java read MOCKARTY_BASE_URL and MOCKARTY_API_KEY when you omit those constructor arguments; Java also reads MOCKARTY_NAMESPACE. Go takes its URL in NewClient and uses WithAPIKey and WithNamespace for the other values. In Python, pass namespace= explicitly; the core Python client does not read MOCKARTY_NAMESPACE automatically.
| Variable | Description | Default |
|---|---|---|
MOCKARTY_BASE_URL |
Server URL for Python and Java | http://localhost:5770 |
MOCKARTY_API_KEY |
API token for Python and Java | (none) |
MOCKARTY_NAMESPACE |
Default namespace for Java; Python test plugins also use it | sandbox |
API Reference
Mocks API
Create, read, update, and delete mocks. Supports batch operations, soft delete/restore, versioning, and log access.
Go
// Create
resp, err := client.Mocks().Create(ctx, mock)
// Get / List
mock, err := client.Mocks().Get(ctx, "mock-id")
list, err := client.Mocks().List(ctx, &mockarty.ListMocksOptions{
Namespace: "production",
Tags: []string{"users"},
Limit: 20,
})
// Update / Delete / Restore
updated, err := client.Mocks().Update(ctx, "mock-id", mock)
err = client.Mocks().Delete(ctx, "mock-id")
err = client.Mocks().Restore(ctx, "mock-id")
// Batch operations
err = client.Mocks().BatchCreate(ctx, mocks)
err = client.Mocks().BatchDelete(ctx, ids)
err = client.Mocks().BatchRestore(ctx, ids)
// Logs and versions
logs, err := client.Mocks().Logs(ctx, "mock-id", &mockarty.LogsOptions{Limit: 50})
versions, err := client.Mocks().ListVersions(ctx, "mock-id")
version, err := client.Mocks().GetVersion(ctx, "mock-id", "v2")
err = client.Mocks().RestoreVersion(ctx, "mock-id", "v1")
// Additional operations
patched, err := client.Mocks().Patch(ctx, "mock-id", map[string]any{"priority": 10})
err = client.Mocks().DeleteLogs(ctx, "mock-id")
err = client.Mocks().CopyToNamespace(ctx, []string{"mock-1"}, "production")
err = client.Mocks().MoveToFolder(ctx, []string{"mock-1"}, "folder-id")
err = client.Mocks().BatchUpdateTags(ctx, []string{"mock-1", "mock-2"}, []string{"v2"})
Python
# Create
result = client.mocks.create(mock)
# Get / List
mock = client.mocks.get("mock-id")
page = client.mocks.list(namespace="sandbox", limit=10)
for m in page.items:
print(m.id)
# Delete / Restore
client.mocks.delete("mock-id")
client.mocks.restore("mock-id")
Java
// Create
client.mocks().create(mock);
// Get / List
Mock mock = client.mocks().get("mock-id");
// Delete / Restore
client.mocks().delete("mock-id");
client.mocks().restore("mock-id");
Stores API
Access global and chain stores for stateful mock scenarios.
Go
// Global store
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") // delete multiple keys
// Chain store
chainStore, err := client.Stores().ChainGet(ctx, "chain-id")
err = client.Stores().ChainSet(ctx, "chain-id", "status", "completed")
err = client.Stores().ChainDelete(ctx, "chain-id", "key")
Python
# Global store
client.stores.global_set("counter", 0)
data = client.stores.global_get()
# Chain store
client.stores.chain_set("order-flow", "orderId", "abc-123")
chain_data = client.stores.chain_get("order-flow")
Java
// Global store
client.stores().globalSet("counter", 0);
Map<String, Object> store = client.stores().globalGet();
// Chain store
client.stores().chainSet("registration-flow", "step", "1");
Namespaces API
Create and list namespaces for mock isolation.
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");
Collections & Test Runs API
Manage API test collections: list, create, execute, export, and duplicate.
Go
// List / Get
collections, err := client.Collections().List(ctx)
col, err := client.Collections().Get(ctx, "collection-id")
// Execute a single collection or multiple
result, err := client.Collections().Execute(ctx, "collection-id")
result, err = client.Collections().ExecuteMultiple(ctx, []string{"col-1", "col-2"})
// Create / Update / Delete
created, err := client.Collections().Create(ctx, &mockarty.Collection{Name: "My Suite"})
updated, err := client.Collections().Update(ctx, "collection-id", col)
err = client.Collections().Delete(ctx, "collection-id")
// Export (Postman-compatible JSON)
data, err := client.Collections().Export(ctx, "collection-id")
// Test Runs
runs, err := client.TestRuns().List(ctx)
run, err := client.TestRuns().Get(ctx, "run-id")
err = client.TestRuns().Cancel(ctx, "run-id")
err = client.TestRuns().Delete(ctx, "run-id")
Python
collections = client.collections.list()
result = client.collections.execute("collection-id")
Java
client.collections().list();
client.collections().execute("collection-id");
Performance Testing API
Run load tests, manage configurations and schedules, compare results.
Go
task, err := client.Perf().Run(ctx, &mockarty.PerfConfig{
Name: "load-test-orders",
Duration: "30s",
VUs: 50,
})
err = client.Perf().Stop(ctx, "task-id")
results, err := client.Perf().ListResults(ctx)
result, err := client.Perf().GetResult(ctx, "result-id")
comparison, err := client.Perf().Compare(ctx, []string{"result-1", "result-2"})
// Configs & Schedules
configs, err := client.Perf().ListConfigs(ctx)
schedules, err := client.Perf().ListSchedules(ctx)
Python
task = client.perf.run(config)
client.perf.stop("task-id")
results = client.perf.list_results()
Java
client.perf().run(config);
client.perf().stop("task-id");
client.perf().listResults();
Load-test DSL → k6 script
Author a load test with a fluent builder and export it as a k6-compatible
JavaScript script — no hand-writing k6 boilerplate. The generated script is
self-contained: your target() is baked in as a runnable default
(const BASE_URL = __ENV.BASE_URL || '…'), so it works out of the box and stays
overridable at run time with mockarty-cli perf run script.js -e BASE_URL=….
Terminal methods:
toK6Script()/to_k6_script()— the k6 JS string (write to a.jsfile, run anywhere k6 ormockarty-cli perf runruns).toPerfConfig()/to_perf_config()— a perf-config object (script + vus/duration/stages/thresholds/env) formockarty-cli perf run --from-config.save(path)/SaveConfig(path)— write that perf-config JSON to disk.
Go
script := mockarty.NewLoadTest("checkout-load").
Target("http://localhost:5770").
Get("/health").
Post("/stubs/sandbox/v1/charge", map[string]any{"amount": 100}).
Stages(mockarty.Stage("30s", 20), mockarty.Stage("1m", 20), mockarty.Stage("10s", 0)).
ThinkTime(0.5).
Threshold("http_req_duration", "p(95)<500").
ToK6Script()
os.WriteFile("checkout.js", []byte(script), 0o644)
// then: mockarty-cli perf run checkout.js
Python
from mockarty import LoadTest
script = (
LoadTest("checkout-load")
.target("http://localhost:5770")
.get("/health")
.post("/stubs/sandbox/v1/charge", body={"amount": 100})
.stages([("30s", 20), ("1m", 20), ("10s", 0)])
.think_time(0.5)
.threshold("http_req_duration", "p(95)<500")
.to_k6_script()
)
open("checkout.js", "w").write(script)
# then: mockarty-cli perf run checkout.js
Java
String script = LoadTestBuilder.named("checkout-load")
.target("http://localhost:5770")
.get("/health")
.post("/stubs/sandbox/v1/charge", Map.of("amount", 100))
.stage("30s", 20).stage("1m", 20).stage("10s", 0)
.thinkTime(0.5)
.threshold("http_req_duration", "p(95)<500")
.toK6Script();
Files.writeString(Path.of("checkout.js"), script);
// then: mockarty-cli perf run checkout.js
The three SDKs emit an identical script for the same DSL, so a load profile
authored in one language runs unchanged everywhere.
Fuzzing API
Start security fuzzing sessions, manage configurations, and triage findings.
Go
task, err := client.Fuzzing().Start(ctx, &mockarty.FuzzingConfig{
Name: "fuzz-users-api",
TargetURL: "http://localhost:5770",
})
err = client.Fuzzing().Stop(ctx, "run-id")
result, err := client.Fuzzing().GetResult(ctx, "run-id")
findings, err := client.Fuzzing().ListFindings(ctx)
finding, err := client.Fuzzing().GetFinding(ctx, "finding-id")
err = client.Fuzzing().TriageFinding(ctx, "finding-id", "accepted", "Known behavior")
// Quick fuzz, schedules, and imports
summary, err := client.Fuzzing().GetSummary(ctx)
schedules, err := client.Fuzzing().ListSchedules(ctx)
Python
task = client.fuzzing.start(config)
findings = client.fuzzing.list_findings()
Java
client.fuzzing().start(config);
client.fuzzing().listFindings();
Contract Testing API
Validate mocks against API specifications, verify providers, manage Pact contracts, run can-i-deploy checks, and use the API Registry for cross-team contract governance.
Go
// Validate mocks against an OpenAPI/Swagger spec
result, err := client.Contracts().ValidateMocks(ctx, &mockarty.ContractValidationRequest{
SpecURL: "https://petstore.swagger.io/v2/swagger.json",
Namespace: "production",
})
// Verify a live provider against a contract
verify, err := client.Contracts().VerifyProvider(ctx, &mockarty.ContractValidationRequest{
SpecURL: "https://api.example.com/openapi.json",
TargetURL: "https://api.example.com",
})
// Pact support
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")
// Detect drift between contract and live service
drift, err := client.Contracts().DetectDrift(ctx, driftReq)
// API Registry: publish, subscribe, check breaking changes
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 & Results
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("");
Recorder API
Capture live traffic and generate mocks from recorded requests.
Go
// Start a recording session
session, err := client.Recorder().StartRecording(ctx, &mockarty.RecorderSession{
Name: "capture-login-flow",
TargetURL: "https://api.example.com",
})
// Manage sessions
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")
// Work with recorded entries
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")
// Generate mocks from recorded traffic
mocks, err := client.Recorder().CreateMocksFromSession(ctx, "session-id", nil)
// Export session as HAR
har, err := client.Recorder().ExportSession(ctx, "session-id")
// CA certificate management (for HTTPS recording)
caStatus, err := client.Recorder().GetCAStatus(ctx)
err = client.Recorder().GenerateCA(ctx)
caCert, err := client.Recorder().DownloadCA(ctx)
Python
session = client.recorder.start_recording(config)
client.recorder.stop_recording("session-id")
entries = client.recorder.get_entries("session-id")
mocks = client.recorder.create_mocks_from_session("session-id")
Java
RecorderSession s = client.recorder().startRecording(config);
client.recorder().listSessions();
client.recorder().getSession("session-id");
client.recorder().stopRecording("session-id");
client.recorder().getEntries("session-id");
client.recorder().createMocksFromSession("session-id", null);
Health API
Check server health, liveness, and 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();
Chaos Engineering API
Preview. Run controlled fault injection experiments on Kubernetes clusters. Check the available safeguards on your installation before starting. See the Chaos Engineering Guide.
Go
// Cluster profiles (connect to 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)
// List presets (predefined experiment templates)
presets, err := client.Chaos().ListPresets(ctx)
// Create and run experiment
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)
// Monitor experiment
metrics, err := client.Chaos().GetMetrics(ctx, exp.ID)
events, err := client.Chaos().GetEvents(ctx, exp.ID)
err = client.Chaos().Abort(ctx, exp.ID) // emergency stop
// Get report and download
report, err := client.Chaos().GetReport(ctx, exp.ID)
htmlReport, err := client.Chaos().DownloadReport(ctx, exp.ID, "html")
// Cluster operations (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)
// Operator management
opStatus, err := client.Chaos().GetOperatorStatus(ctx, "chaos-system")
manifest, err := client.Chaos().GenerateOperatorManifest(ctx, "https://mockarty.example.com", "")
Python
# List presets
presets = client.chaos.list_presets()
# Create and run experiment
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"])
# Get report
report = client.chaos.get_report(exp["id"])
Java
// Create and run experiment
ChaosExperiment exp = client.chaos().create(new ChaosExperiment()
.setName("pod-kill-test")
.setNamespace("staging")
.setDurationSec(300));
client.chaos().run(exp.getId());
// Get report
Map<String, Object> report = client.chaos().getReport(exp.getId());
Mock Builder (Fluent API)
All SDKs provide a fluent builder for constructing mocks with full type safety.
HTTP Mock with Conditions
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("$.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("$.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 Mock
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 Mock
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();
Proxy and OneOf
Go
// Proxy to a real backend
proxy := mockarty.NewMockBuilder().
ID("proxy").
HTTP(func(h *mockarty.HTTPBuilder) {
h.Route("/api/external").Method("GET")
}).
ProxyTo("https://real-api.example.com").
Build()
// OneOf responses (random or sequential)
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
proxy = (
MockBuilder.http("/api/external", "GET")
.id("proxy")
.proxy_to("https://real-api.example.com")
.build()
)
Java
// Proxy
Mock proxy = MockBuilder.http("/api/real-service", "GET")
.proxyTo("https://api.example.com")
.build();
// OneOf responses (ordered)
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();
Error Handling
The Mockarty REST API emits a single uniform JSON envelope for every 4xx/5xx
failure:
{
"error": "human-readable, sanitized message",
"code": "not_found",
"request_id": "8c3a…d12"
}
error— safe message; never contains SQL strings, stack traces, or file
paths. Display directly to end users.code— stable machine-readable identifier from a closed set
(validation,unauthorized,forbidden,not_found,conflict,
rate_limit,unavailable,external,internal). Branch on this
field instead of parsing the message.request_id— server-side correlation ID. Include in support tickets so
operators can locate the matching log line.
Each SDK parses the envelope and exposes typed exceptions / sentinel errors
that match the code field. Older Mockarty servers emit only error; the
SDKs and CLI fall back to HTTP-status dispatch in that case.
Go
import "errors"
_, err := client.Mocks().Get(ctx, "nonexistent")
if errors.Is(err, mockarty.ErrNotFound) {
// Handle 404 — works against both new (code="not_found") and legacy servers.
}
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"not found (request_id={e.request_id})")
except MockartyAPIError as e:
# e.code is the stable kind ("validation", "rate_limit", ...).
# e.request_id is the server-side 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("Mock not found");
} catch (MockartyException e) {
System.out.printf("API error %d: %s%n", e.getStatusCode(), e.getMessage());
}
Testing Integration
Go: Testing Helpers
The Go SDK provides *T helper methods that automatically clean up resources when the test ends:
func TestUserAPI(t *testing.T) {
client := mockarty.NewClient("http://localhost:5770",
mockarty.WithAPIKey("mk_test_key"),
)
// Create namespace with auto-cleanup
client.SetupNamespaceT(t, "test-ns")
// Create mock with auto-cleanup
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 is automatically deleted when the test ends
_ = mock
}
Python: pytest Fixtures
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 Extension
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());
// Your test code here...
// Mocks are automatically cleaned up after each test
}
}
Kotlin: DSL in Tests
@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")
}
}
// Test assertions here...
}
}
Best Practices
-
Use namespaces for isolation. Each test suite or environment should use its own namespace to avoid mock conflicts.
-
Set TTL on test mocks. Always set a
ttlon mocks created during testing so they are automatically cleaned up even if your teardown fails. -
Use the mock builder for type safety. The fluent builder API catches errors at compile time (or IDE time) rather than at runtime.
-
Clean up mocks after tests. Use the built-in test helpers (
SetupNamespaceTin Go,mock_cleanupin Python,@MockartyTestin Java/Kotlin) for automatic cleanup. -
Use stores for stateful scenarios. Chain stores allow you to simulate multi-step workflows (e.g., create order -> pay -> ship) with state carried between mock calls.
-
Keep credentials in CI secrets. Pass the server URL and API token to your client from the pipeline environment. Python and Java can read the variables above automatically; in Go, read them and pass them to
NewClientandWithAPIKey. -
Use batch operations for setup. When creating multiple mocks for a test scenario, use
BatchCreateto reduce HTTP round-trips. -
Version your mocks. Use the versioning API to track mock changes and roll back when needed.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
MockartyConnectionError / connection refused |
Mockarty server not running, or base_url points to the wrong host/port |
Check the configured URL and that its /health endpoint returns HTTP 200 |
MockartyUnauthorizedError (401) |
Missing or invalid API token | Create a token in Admin → API Tokens and pass it to the client as shown above |
MockartyForbiddenError (403) with invalid license |
No valid license applied to the server | Apply a license key in Administration → License, or contact your administrator |
MockartyForbiddenError (403) on namespace |
Token scoped to a different namespace | Use a token with access to the target namespace, or switch namespaces in the client |
MockartyConflictError (409) on create |
Mock with the same ID already exists | Use upsert/update, or generate a unique ID |
MockartyNotFoundError on resolve |
Mock exists but namespace/route/method don’t match | Confirm the mock fields via list or the UI; check for trailing slashes and method case |
| Faker placeholders show as literal strings in the response | payload sent as a plain string instead of a template object |
Pass a dict/Map with "$.fake.*" values, not a pre-rendered string |
| Request times out | The server or network did not respond within the configured timeout | Check server reachability; adjust the timeout if this operation needs longer than the default 30 seconds |
| Tests fail intermittently in parallel | Multiple tests sharing the same namespace and mock IDs | Use a unique namespace per test suite or randomize mock IDs |
For protocol-specific troubleshooting (gRPC, MCP, Kafka, etc.), see the relevant section in the API Reference.
Test framework integration
Each SDK ships a framework layer that hooks into your favourite test
runner so the per-test outcome — status, steps, captured logs, small
attachments — flows back to a Mockarty test case as a synthetic case
run. You decorate the test, run it, and the case-run history appears in
the UI without writing any glue code.
Python — pytest plugin
After pip install mockarty the pytest plugin auto-loads. Set
MOCKARTY_BASE_URL and MOCKARTY_API_KEY (or pass mockarty_client as
a fixture) and decorate the tests you want to track:
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")binds the test to an existing case. Pass
auto_create=Truewithname="..."to create the case the first
time the test runs.@attach_reportopts the test into the upload.with step("...")records a TCM step. Steps nest. When
allure-pytestis installed each step is mirrored to Allure too.attach(name, body, content_type=...)adds a small artefact that
shows up next to the case run in the UI.
Java — JUnit 5 extension
Add mockarty-junit5 to your test dependencies and put @MockartyTest
on the class. Per-method annotations control case binding:
@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()));
}
}
The same primitives are available through Step.open(...) /
Step.run(...) and Attachments.attach(...).
Go — testing.T helpers
The Go SDK exposes helpers to bind a *testing.T to a Mockarty
namespace and clean up created mocks on test exit. To trigger a Test
Plan run from a Go test and assert on its outcome:
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") // fails the test on plan-run failure
}
Defaults
All three frameworks fail-soft: when no Mockarty client is reachable
(missing env, server unreachable) the decorators / annotations no-op so
the test still runs locally. The framework never fails your test
because reporting failed.
Related Documentation
Reports from selected CI jobs
When Mockarty starts a saved CI job for selected test cases, it supplies a private
MOCKARTY_CI_CONTEXT environment variable. The SDK’s existing external-run
Report operation uses that context to match the test’s stable ID and full name
against the selected items. Send the same identities configured for the selected
test. An unknown or ambiguous identity is rejected; the SDK does not create a
replacement case or attach the result to another launch.
Upload every selected result, then report the command outcome once with
CompleteGroup (Go), complete_group (Python), or completeGroup (Java).
Use passed, failed, or cancelled. A passed command does not make missing test
results pass. The group remains accountable for all selected items.
For example, Python code running inside the job can finish its uploads as follows:
import os
from mockarty.ci_job_context import load_ci_job_context
job = load_ci_job_context(os.environ["MOCKARTY_CI_CONTEXT"])
# Upload the test results with client.external_runs.report(...).
client.external_runs.complete_group(job.callback, "passed", namespace=job.namespace)
Go uses LoadCIJobContext, job.Callback() and
client.ExternalRuns().CompleteGroup(ctx, job.Namespace, job.Callback(), status).
Java uses CIJobContext.load, job.callback() and
client.externalRuns().completeGroup(job.getNamespace(), job.callback(), status).
Existing Report signatures and ordinary uploads remain available.
Keep the private context out of logs, labels, parameters and environment report
files. SDK environment writers omit it; selected uploads also remove it from
metadata and reject attachments containing its value. Selected result and group
completion POSTs are not automatically retried after an uncertain response.
Inspect the existing launch before an explicit retry.
For Allure directories, UploadAllureDir / upload_allure_dir /
uploadAllureDir filters matching selected results before resolving their
media, and preflights every selected body before the first result request.
Selected reports allow up to 1000 steps, 256 KiB per inline attachment and
1 MiB of inline attachments per result. Use the CLI for large files and
container fixtures, and call group completion after the uploads.
The Go incremental externalruns.Client write methods refuse selected job
context; use the finalized ExternalRuns().Report workflow shown above.