# Go testing

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

## Mock client

```go
import "github.com/Censkh/CalmLens/packages/go-sdk/calmlenstest"

mock, err := calmlenstest.NewClient(calmlenstest.Options{ProjectID: "project"})
if err != nil {
    log.Fatal(err)
}
asset, err := mock.Assets.Moderate(ctx, calmlens.SubmitAssetOptions{Name: "text", Content: &calmlens.Content{Type: "text/plain", PlainText: calmlens.Ptr("Hello")}})
```

The mock embeds the real client, so your code receives the same types and errors as in production. It accepts the same `ProjectID`, `BaseURL`, `Timeout` and `MaxRetries` options as the real client; retries are off unless you set `MaxRetries`.

## What the mock simulates

- **Errors** use the API's codes, HTTP statuses and error body, for example `404` with `asset/not-found` and `409` with `folder/not-empty`, and every response has an `X-Request-Id`.
- **Lists** apply `Filter` (RSQL), `Ordering`, `FolderID` and paging. **Search** matches keywords in names, IDs, external IDs, descriptions and tags.
- **Multipart uploads** keep the queue mode chosen at the start, check part numbers and `TotalSizeInBytes`.
- **Idempotency keys** replay the first response, and a key reused for a different request returns `idempotency/key-reused`.
- **Events** you add with `mock.EnqueueEvent(...)` are returned by `Events.List` and `Events.ListAll` after cursors taken earlier.
- **CDN responses** from `CDN.Serve` include the content type and length and support single byte ranges.

## Inspect requests and simulate failures

`mock.Requests()` returns every captured request with its method, path, parsed query and decoded body, and `mock.FailNext(err)` makes the next request fail with `sdk/transport-error` (or `sdk/timeout` for `context.DeadlineExceeded`). Use `mock.WithStorage(func(db, images) { ... })` to change stored assets safely while other goroutines send requests.

The mock returns configured decisions; it does not classify content, fetch remote URLs or transform media, and its signed URLs are not production URLs.
