# Java testing

Test your integration without API calls using the [Java SDK](/docs/sdk/java).

## Mock client

`MockCalmLensClient` wraps a real client whose transport answers from a queue, so validation, encoding, retries and error mapping all run offline. It records every request.

```java
import com.calmlens.CalmLensClient;
import com.calmlens.ErrorCodes;
import com.calmlens.MockCalmLensClient;
import java.util.List;
import java.util.Map;

var mock = new MockCalmLensClient(CalmLensClient.builder("unused", "project-9").maxRetries(0));
mock.enqueue(200, Map.of("id", "asset-1", "status", "approved"));
mock.enqueueError(ErrorCodes.ASSET_NOT_FOUND);
mock.enqueueEvents("cursor-2", false, Map.of("id", "event-1", "type", "asset.rejected", "assetId", "asset-1"));
mock.enqueueCdn(200, "image/webp", imageBytes);

// ... exercise code under test, then inspect what it sent:
MockCalmLensClient.Request sent = mock.requests().get(0);
sent.method();                    // "POST"
sent.path();                      // "/v1/projects/project-9/assets/upload"
sent.query();                     // decoded parameters, e.g. {queue=false, name=text, contentType=text/plain, ...}
sent.header("Idempotency-Key");   // generated for each upload
sent.bodyText();                  // request body as UTF-8 (null when there is none)
```

- `enqueue(status, body)` queues a JSON response from a map, list or response record. `enqueue(method, path, status, body)` answers only a request to that route.
- `enqueueError(code)` queues the API's error response for a public error code, with its real HTTP status, error body and request ID.
- `enqueueRateLimited(seconds)`, `enqueueFailure(exception)` and `enqueueTimeout()` simulate throttling and network failures.
- `enqueueEvents(cursor, hasMore, events...)` and `enqueueCdn(status, contentType, bytes)` queue an events page and a CDN response.

Like the real client, the mock retries reads and uploads after 429, 502, 503 and 504 responses and network failures, without waiting. Queue one response per attempt, or build it with `maxRetries(0)` as above. A request with an empty queue fails with `sdk/transport-error`. Mocks do not classify content or keep state between requests.
