Rust testing

Test your integration without API calls using the Rust SDK. The mock is behind the testing feature, so enable it for tests only:

[dev-dependencies]
calmlens = { version = "0.1", features = ["testing"] }

Mock client

MockClient answers requests from a queue and records them. It runs the real client's validation, request encoding, retries and error handling, and creates no HTTP client, so you can use it inside any async runtime.

use calmlens::{models::*, testing::MockClient};

#[tokio::test]
async fn reports_timeouts() -> calmlens::Result<()> {
    let mock = MockClient::new()?;
    mock.enqueue_timeout();
    let error = mock.events().list(ListEvents::default()).await.unwrap_err();
    assert!(error.is_timeout());
    let request = mock.last_request().unwrap();
    assert_eq!(request.path, "/v1/projects/project-1/events");
    Ok(())
}

Queue responses with:

MethodQueues
enqueue(status, model)A JSON response from a model or serde_json::Value
enqueue_api_error(code, message)The API's error for code, with the HTTP status the API uses for it
enqueue_response(MockResponse)A response with headers, such as a CDN response with content-type or a 429 with retry-after
enqueue_raw(status, bytes)A raw body
enqueue_timeout(), enqueue_transport_error(message), enqueue_error(error)A failure

requests() and last_request() return the captured requests with their method, url, path, decoded query (query_param(name)), headers (header(name)), body and json(). Streamed uploads are captured too. An empty queue fails with sdk/transport-error without making network calls. Mocks don't classify content or keep backend state.

MockClient::new() turns retries off, so each call uses one queued response. To test retries, build the mock like a real client: MockClient::from_builder(Client::builder(key, project).max_retries(2)).

Code that owns its client

When the code under test takes a Client, pass it mock.client(). The returned client answers from the same queue and records its requests in the same log. With the blocking feature, mock.blocking()? returns a blocking::Client wired to the same queue.

use calmlens::{models::*, testing::MockClient, Client};

async fn moderate_bio(client: Client, bio: &str) -> calmlens::Result<Asset> {
    client.assets().moderate(SubmitAsset::text(bio)).await
}

#[tokio::test]
async fn approves_bios() -> calmlens::Result<()> {
    let mock = MockClient::new()?;
    mock.enqueue(200, Asset::new("asset-1", AssetStatus::Approved));
    let asset = moderate_bio(mock.client(), "Hello").await?;
    assert_eq!(asset.id, "asset-1");
    assert_eq!(mock.requests().len(), 1);
    Ok(())
}

Webhook handlers

Sign test deliveries with create_webhook_signature_header, and build a delivery body from an event with WebhookEventPayload::from_event, the same conversion CalmLens applies before sending.

Signing in

Signing out

Cookies on CalmLens

We use essential cookies to keep you signed in and the site secure. With your permission, we'll also use functional cookies to remember preferences such as your layout and documentation language, and to offer Google One Tap sign-in. We don't use analytics or advertising cookies. Manage cookies