or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

error-simulation.mdhttp-methods.mdindex.mdmock-adapter.mdresponses.md
tile.json

error-simulation.mddocs/

Error Simulation

Advanced error simulation capabilities for testing error handling and network failure scenarios. The RequestHandler interface provides methods for simulating various types of network errors, timeouts, and request failures.

Capabilities

Pass Through

Forward matched requests to the actual network instead of mocking them.

/**
 * Forward the matched request to actual network
 * @returns AxiosMockAdapter for chaining
 */
passThrough(): AxiosMockAdapter;

Usage Examples:

// Mock POST requests but let GET requests through
mock
  .onPost(/^\/api/)
  .reply(201)
  .onGet(/^\/api/)
  .passThrough();

// Mock specific requests, let everything else through
mock
  .onGet("/foo")
  .reply(200)
  .onPut("/bar", { xyz: "abc" })
  .reply(204)
  .onAny()
  .passThrough();

// Conditional pass-through based on headers
mock.onGet("/api").reply(function(config) {
  if (config.headers.Environment === "production") {
    // Can't return passThrough() from callback, but can forward manually
    return axios.get(config.url, { headers: config.headers });
  }
  return [200, { mock: true }];
});

Network Error

Simulate network connectivity errors.

/**
 * Simulate network error (reusable)
 * @returns AxiosMockAdapter for chaining
 */
networkError(): AxiosMockAdapter;

/**
 * Simulate network error (single use)
 * @returns AxiosMockAdapter for chaining
 */
networkErrorOnce(): AxiosMockAdapter;

Usage Examples:

// All requests to /users will fail with network error
mock.onGet("/users").networkError();

// First request fails, subsequent requests would get 404
mock.onGet("/users").networkErrorOnce();

// Test error handling
try {
  await axios.get("/users");
} catch (error) {
  console.log(error.message); // "Network Error"
  console.log(error.isAxiosError); // true
}

Timeout Error

Simulate request timeout scenarios.

/**
 * Simulate timeout error (reusable)
 * @returns AxiosMockAdapter for chaining
 */
timeout(): AxiosMockAdapter;

/**
 * Simulate timeout error (single use)
 * @returns AxiosMockAdapter for chaining
 */
timeoutOnce(): AxiosMockAdapter;

Usage Examples:

// All requests to /slow will timeout
mock.onGet("/slow").timeout();

// Only first request times out
mock.onGet("/slow").timeoutOnce();

// Test timeout handling
try {
  await axios.get("/slow", { timeout: 5000 });
} catch (error) {
  console.log(error.code); // "ECONNABORTED" or "ETIMEDOUT"
  console.log(error.message); // "timeout of 5000ms exceeded"
}

Aborted Request

Simulate request abortion scenarios.

/**
 * Simulate aborted request (reusable)
 * @returns AxiosMockAdapter for chaining
 */
abortRequest(): AxiosMockAdapter;

/**
 * Simulate aborted request (single use)
 * @returns AxiosMockAdapter for chaining
 */
abortRequestOnce(): AxiosMockAdapter;

Usage Examples:

// All requests to /cancel will be aborted
mock.onGet("/cancel").abortRequest();

// Only first request is aborted
mock.onGet("/cancel").abortRequestOnce();

// Test abort handling
try {
  await axios.get("/cancel");
} catch (error) {
  console.log(error.code); // "ECONNABORTED"
  console.log(error.message); // "Request aborted"
}

Error Patterns

Progressive Failure

Simulate scenarios where requests initially succeed but then start failing.

// First few requests succeed, then start failing
mock
  .onGet("/api")
  .replyOnce(200, { data: "success" })
  .onGet("/api")
  .replyOnce(200, { data: "success" })
  .onGet("/api")
  .networkError(); // All subsequent requests fail

Intermittent Failures

Use callback functions to simulate intermittent network issues.

mock.onGet("/flaky").reply(function(config) {
  if (Math.random() < 0.3) {
    // 30% chance of network error
    throw new Error("Network Error");
  }
  return [200, { status: "ok" }];
});

Timeout Scenarios

Test different timeout configurations.

// Quick timeout
mock.onGet("/fast").timeout();

// With custom timeout message
mock.onGet("/custom").reply(function(config) {
  throw {
    code: "ECONNABORTED",
    message: config.timeoutErrorMessage || `timeout of ${config.timeout}ms exceeded`
  };
});

Error Status Codes

Simulate various HTTP error status codes with proper error responses.

// Client errors
mock.onGet("/unauthorized").reply(401, { error: "Unauthorized" });
mock.onGet("/forbidden").reply(403, { error: "Forbidden" });
mock.onGet("/not-found").reply(404, { error: "Not Found" });
mock.onPost("/invalid").reply(422, { 
  error: "Validation failed",
  details: ["Name is required", "Email is invalid"]
});

// Server errors
mock.onGet("/server-error").reply(500, { error: "Internal Server Error" });
mock.onGet("/bad-gateway").reply(502, { error: "Bad Gateway" });
mock.onGet("/service-unavailable").reply(503, { error: "Service Unavailable" });

Async Error Handling

Promise-Based Errors

Simulate asynchronous errors using promises.

mock.onGet("/async-error").reply(function(config) {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      // Simulate async failure
      resolve([500, { error: "Async operation failed" }]);
    }, 100);
  });
});

Network Error with Delay

Combine delays with network errors for realistic simulation.

mock.onGet("/delayed-failure")
  .withDelayInMs(2000)
  .networkError();

// Request will wait 2 seconds then fail with network error

Error Response Details

Axios Error Structure

Understanding the error objects created by different simulation methods:

// Network Error structure
{
  message: "Network Error",
  isAxiosError: true,
  config: { /* original request config */ },
  code: undefined,
  response: undefined
}

// Timeout Error structure
{
  message: "timeout of 5000ms exceeded",
  isAxiosError: true,
  config: { /* original request config */ },
  code: "ECONNABORTED" // or "ETIMEDOUT"
}

// Abort Error structure
{
  message: "Request aborted",
  isAxiosError: true,
  config: { /* original request config */ },
  code: "ECONNABORTED"
}

// HTTP Error structure (status >= 400)
{
  message: "Request failed with status code 404",
  isAxiosError: true,
  config: { /* original request config */ },
  response: {
    status: 404,
    data: { error: "Not Found" },
    headers: {}
  }
}

Could Not Find Mock Error

When onNoMatch: "throwException" is configured, unmatched requests throw specific errors:

const mock = new AxiosMockAdapter(axios, { onNoMatch: "throwException" });

try {
  await axios.get("/unmatched");
} catch (error) {
  console.log(error.isCouldNotFindMockError); // true
  console.log(error.method); // "get"
  console.log(error.url); // "/unmatched"
  console.log(error.message); // Detailed JSON of the unmatched request
}

Testing Error Scenarios

Error Recovery Testing

Test how your application handles and recovers from errors.

describe("API Error Handling", () => {
  it("should retry on network error", async () => {
    const mock = new AxiosMockAdapter(axios);
    
    // First request fails, second succeeds
    mock
      .onGet("/data")
      .networkErrorOnce()
      .onGet("/data")
      .reply(200, { data: "success" });

    // Your retry logic here
    const result = await retryableRequest("/data");
    expect(result.data).toEqual({ data: "success" });
  });
});

Timeout Handling

Test timeout scenarios with different configurations.

describe("Timeout Handling", () => {
  it("should handle request timeout", async () => {
    const mock = new AxiosMockAdapter(axios);
    mock.onGet("/slow").timeout();

    try {
      await axios.get("/slow", { timeout: 1000 });
      fail("Should have thrown timeout error");
    } catch (error) {
      expect(error.code).toBe("ECONNABORTED");
    }
  });
});

Circuit Breaker Testing

Test circuit breaker patterns with progressive failures.

// Simulate circuit breaker scenario
for (let i = 0; i < 5; i++) {
  mock.onGet("/api").networkErrorOnce();
}
// After 5 failures, circuit should open
mock.onGet("/api").reply(200, { status: "recovered" });