---
title: "Testing"
description: "Test code that uses the workers-ai provider. Use Laravel AI fakes, Classification::fake(), Extraction::fake() and Http::fake()."
---

> Documentation Index
> Fetch the complete documentation index at: https://laravel-cf-workersai-docs.mdick85.workers.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing

You do not need Cloudflare credentials to test your own code. Use the fakes in this page. The `Http::fake` example needs a fake token and account ID in config.

The examples use Pest. For PHPUnit, put the same calls in a test method and use `$this->assertSame(...)` in place of `expect(...)->toBe(...)`.

## Fake an agent

```php
SupportAgent::fake(['Reset it from the login page.']);

$response = (new SupportAgent)->prompt('How do I reset my password?');

expect($response->text)->toBe('Reset it from the login page.');

SupportAgent::assertPrompted('How do I reset my password?');
```

With no list of responses, the fake returns `Fake response for prompt: ` followed by the first 10 words of the prompt. You can pass a closure that receives the prompt.

The fake replaces the gateway, so no request reaches the package. Use it to test your own logic.

## Fake embeddings

```php
use Laravel\Ai\Embeddings;

Embeddings::fake();

// run your code, then:
Embeddings::assertGenerated(fn ($prompt) => $prompt->inputs === ['hello']);
```

## Fake the HTTP layer

To run the real package code, fake the HTTP call. This tests the request body and the response handling.

```php
use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Http;

config([
    'ai.providers.workers-ai' => [
        'driver' => 'workers-ai',
        'key' => 'test-key',
        'account_id' => 'test-account',
    ],
]);

Http::fake([
    'api.cloudflare.com/*' => Http::response([
        'id' => 'chatcmpl-1',
        'object' => 'chat.completion',
        'model' => '@cf/meta/llama-3.3-70b-instruct-fp8-fast',
        'choices' => [[
            'index' => 0,
            'message' => ['role' => 'assistant', 'content' => 'Hello'],
            'finish_reason' => 'stop',
        ]],
        'usage' => ['prompt_tokens' => 10, 'completion_tokens' => 2, 'neurons' => 1.5],
    ]),
]);

$response = agent('You are a helpful assistant.')->prompt('Hi', provider: 'workers-ai');

Http::assertSent(fn (Request $request) => str_ends_with($request->url(), '/chat/completions'));
```

If your test config sets `gateway`, use the pattern `gateway.ai.cloudflare.com/*`.

## Fake images, speech, transcription and reranking

Laravel AI's fakes work on this provider, and send no request. See [Image generation](/docs/guides/images/#test-your-code), [Speech and transcription](/docs/guides/audio/#test-your-code) and [Reranking](/docs/guides/reranking/#test-your-code).

```php
use Laravel\Ai\Audio;
use Laravel\Ai\Image;
use Laravel\Ai\Reranking;
use Laravel\Ai\Transcription;

Image::fake();
Audio::fake();
Transcription::fake(['Hello']);
Reranking::fake();
```

## Test the neuron event

```php
use Illuminate\Support\Facades\Event;
use Meirdick\WorkersAi\Events\WorkersAiUsageReported;

Event::fake([WorkersAiUsageReported::class]);

// Http::fake(...) as above, then call the agent.

Event::assertDispatched(WorkersAiUsageReported::class);
```

## Fake Clef

Clef uses the Laravel AI classification API. Call `Classification::fake()` with one array per expected call. Each array maps a question key to an answer object.

```php
use Laravel\Ai\Classification;
use Laravel\Ai\Classification\Boolean;
use Laravel\Ai\Prompts\ClassificationPrompt;
use Laravel\Ai\Responses\Data\BooleanAnswer;

Classification::fake([
    ['decision' => new BooleanAnswer(0.92)],
]);

$response = Classification::of('Checkout is down.')
    ->question('decision', new Boolean('Is this urgent?'))
    ->classify(provider: 'workers-ai');

expect($response['decision']->isTrue())->toBeTrue();

Classification::assertClassified(fn (ClassificationPrompt $prompt) => $prompt->contains('Checkout') && $prompt->asks('decision'));
```

A question with no answer in the fake gets a random answer of the right shape. Give an answer for every question your test reads. `assertNotClassified()` and `assertNothingClassified()` also exist. `Str::decide()` asks one question with the key `decision`, so the same fake works for it.

Clef needs `laravel/ai` 1.0 or later. The fake sends no request.

## Fake Clairic

`laravel/ai` has no extraction API, so the package adds `Meirdick\WorkersAi\Extraction::fake()`. Give one array per expected call. Each array maps a field name to a value.

```php
use Meirdick\WorkersAi\Extraction;
use Meirdick\WorkersAi\Extraction\Number;
use Meirdick\WorkersAi\Extraction\Text;
use Meirdick\WorkersAi\Prompts\ExtractionPrompt;

Extraction::fake([
    ['total' => 1080],
]);

$invoice = Extraction::of('An invoice for Dana.')
    ->fields(['total' => new Number, 'po' => new Text])
    ->extract();

expect($invoice['total']->value())->toBe(1080)
    ->and($invoice['po']->value())->toBeNull()
    ->and($invoice['po']->pNull())->toBe(1.0);

Extraction::assertExtracted(fn (ExtractionPrompt $prompt) => $prompt->contains('Dana') && $prompt->asks('total'));
```

A field with no value in the fake is `null` with `pNull()` of `1.0`, the same as a real answer when the text does not determine the field. A call past the end of your list also returns `null` for every field.

You can pass a closure that receives the `ExtractionPrompt` and returns the map. Use `Extraction::isFaked()` to check the state. The assertions are `assertExtracted()`, `assertNotExtracted()` and `assertNothingExtracted()`. The fake sends no request.

## Test the extraction events

Each Clairic call dispatches `Extracting`, then `Extracted` or `ExtractionFailed`. The events fire with `Extraction::fake()` too, because the fake replaces only the HTTP call. Use `Event::fake()` to assert them. See [Exceptions and events](/docs/reference/exceptions-and-events/).

## Live tests

The package repository has live tests that call Cloudflare. They are skipped unless you set `WORKERS_AI_E2E_TOKEN` and `WORKERS_AI_E2E_ACCOUNT`. Set `WORKERS_AI_E2E_GATEWAY` for gateway tests, `WORKERS_AI_E2E_WEB_SEARCH=1` for web search, `WORKERS_AI_E2E_ARTIFACTS` to keep generated files, and `WORKERS_AI_E2E_STRESS=1` for the stress sweep. You do not need them to use the package.

Source: https://laravel-cf-workersai-docs.mdick85.workers.dev/docs/guides/testing/index.mdx
