or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdmatching.mdrecording.mdsanitization.mdtest-integration.mdtest-modes.mdtransforms.md
tile.json

matching.mddocs/

Request Matching

Flexible request matching strategies for controlling how recorded requests are matched during playback, with support for custom matching logic and various comparison options for Azure SDK testing scenarios.

Capabilities

Custom Matcher Options

Configuration interface for customizing how requests are matched during playback, providing fine-grained control over comparison behavior.

/**
 * Configuration options for custom request matching during playback
 */
interface CustomMatcherOptions {
  /** Whether to compare request/response bodies during matching */
  compareBodies?: boolean;
  /** List of header names to exclude from matching */
  excludedHeaders?: string[];
  /** Whether to ignore query parameter ordering when matching URLs */
  ignoreQueryOrdering?: boolean;
}

Usage Examples:

import { Recorder } from "@azure-tools/test-recorder";

// Basic custom matcher ignoring certain headers
const matcherOptions: CustomMatcherOptions = {
  excludedHeaders: ["x-ms-client-request-id", "user-agent", "date"]
};

await recorder.setMatcher("CustomDefaultMatcher", matcherOptions);

// Matcher that compares bodies and ignores query order
const strictMatcherOptions: CustomMatcherOptions = {
  compareBodies: true,
  ignoreQueryOrdering: true,
  excludedHeaders: ["authorization", "x-ms-date"]
};

await recorder.setMatcher("CustomDefaultMatcher", strictMatcherOptions);

Setting Request Matchers

Methods for configuring how recorded requests are matched during playback, supporting both predefined and custom matcher strategies.

/**
 * Sets a predefined matcher for request matching during playback
 * @param matcher - The predefined matcher type to use
 */
async setMatcher(matcher: "HeaderlessMatcher" | "BodilessMatcher"): Promise<void>;

/**
 * Sets a custom matcher with specific configuration options
 * @param matcher - The custom matcher type
 * @param options - Optional configuration for the custom matcher
 */
async setMatcher(matcher: "CustomDefaultMatcher", options?: CustomMatcherOptions): Promise<void>;

Usage Examples:

// Use headerless matcher (ignores all headers)
await recorder.setMatcher("HeaderlessMatcher");

// Use bodiless matcher (ignores request/response bodies)
await recorder.setMatcher("BodilessMatcher");

// Use custom matcher with default settings
await recorder.setMatcher("CustomDefaultMatcher");

// Use custom matcher with specific options
await recorder.setMatcher("CustomDefaultMatcher", {
  compareBodies: false,
  excludedHeaders: ["x-ms-client-request-id", "x-ms-date"],
  ignoreQueryOrdering: true
});

Predefined Matcher Types

Built-in matcher strategies that provide common matching behaviors for different testing scenarios.

HeaderlessMatcher

Matches requests while ignoring all HTTP headers, useful when headers contain dynamic or timestamp-based values that change between test runs.

Usage Examples:

// Good for scenarios where headers are highly dynamic
await recorder.setMatcher("HeaderlessMatcher");

// Example: Testing storage operations where headers like x-ms-date change
const blobClient = containerClient.getBlobClient("test.txt");
await blobClient.uploadData(Buffer.from("test content")); // Headers ignored during matching

BodilessMatcher

Matches requests while ignoring request and response bodies, useful for testing scenarios where body content is dynamic but URLs and headers are consistent.

Usage Examples:

// Good for scenarios where request/response bodies are dynamic
await recorder.setMatcher("BodilessMatcher");

// Example: Testing operations with large or dynamic payloads
const searchClient = new SearchClient(endpoint, indexName, credential);
await searchClient.search("*"); // Body content ignored during matching

CustomDefaultMatcher

Flexible matcher that allows fine-tuned control over which aspects of requests are compared during matching.

Usage Examples:

// Typical Azure SDK scenarios - ignore volatile headers but compare bodies
await recorder.setMatcher("CustomDefaultMatcher", {
  compareBodies: true,
  excludedHeaders: [
    "x-ms-client-request-id",
    "x-ms-date", 
    "authorization",
    "user-agent"
  ],
  ignoreQueryOrdering: true
});

// For APIs with stable headers but dynamic bodies
await recorder.setMatcher("CustomDefaultMatcher", {
  compareBodies: false,
  excludedHeaders: ["date", "x-request-id"]
});

Matching Strategy Selection

Guidelines for choosing the appropriate matcher strategy based on your testing scenario.

When to Use HeaderlessMatcher

  • Azure Storage operations with time-sensitive headers
  • APIs that generate unique request IDs or timestamps in headers
  • Services where authentication headers change frequently
  • Scenarios where header variations don't affect functionality
// Storage blob operations with dynamic headers
await recorder.setMatcher("HeaderlessMatcher");

const blobClient = new BlobServiceClient(connectionString, recorder.configureClientOptions({}));
await blobClient.createContainer("test-container"); // x-ms-date and other headers ignored

When to Use BodilessMatcher

  • Operations with large, dynamic request/response bodies
  • APIs where body content changes but request intent remains the same
  • Search operations with variable results
  • Batch operations with different payload sizes
// Search operations with variable results
await recorder.setMatcher("BodilessMatcher");

const searchClient = new SearchClient(endpoint, indexName, credential, recorder.configureClientOptions({}));
await searchClient.search("query", { top: 50 }); // Response body ignored

When to Use CustomDefaultMatcher

  • Most Azure SDK testing scenarios
  • When you need precise control over matching behavior
  • APIs with mix of stable and volatile elements
  • Complex scenarios requiring header filtering
// Typical Azure service testing
await recorder.setMatcher("CustomDefaultMatcher", {
  compareBodies: true, // Compare request/response content
  excludedHeaders: [
    "x-ms-client-request-id", // Always unique
    "x-ms-date",              // Timestamp-based
    "authorization",          // May include dynamic tokens
    "user-agent"              // Environment-dependent
  ],
  ignoreQueryOrdering: true   // Flexible parameter ordering
});

Advanced Matching Scenarios

Complex matching configurations for specialized testing scenarios.

// Scenario: Testing with multiple service versions
await recorder.setMatcher("CustomDefaultMatcher", {
  compareBodies: false, // Bodies may differ between versions
  excludedHeaders: [
    "x-ms-version",     // Service version may vary
    "api-version"       // API version differences
  ]
});

// Scenario: Testing with different authentication methods
await recorder.setMatcher("CustomDefaultMatcher", {
  excludedHeaders: [
    "authorization",           // Different auth tokens
    "x-ms-client-id",         // Different client IDs
    "x-azure-fdid"            // Flight ID differences
  ],
  ignoreQueryOrdering: true
});

// Scenario: Strict matching for critical operations
await recorder.setMatcher("CustomDefaultMatcher", {
  compareBodies: true,         // Must match exactly
  excludedHeaders: [
    "x-ms-client-request-id"   // Only exclude truly random headers
  ],
  ignoreQueryOrdering: false   // Strict parameter ordering
});