The Problem with Testing AI Code
Testing code that calls an external AI API is painful. Hitting OpenAI in your test suite is slow, costs money on every run, and returns non-deterministic responses — making stable assertions nearly impossible. If you've been skipping AI tests for these reasons, this episode of the Ship AI with Laravel series shows you a better path.
Using Pest and the Laravel AI SDK's built-in faking system, you can test your entire AI platform without a single real API call. The pattern mirrors how Laravel already handles faking mail, notifications, and queues — define responses up front, then assert the right prompts went out.
Setting Up the Fake
The SDK's faking system lets you swap out real AI calls with pre-defined responses in your test setup. This gives you deterministic output every time:
use Prism\Prism;
Prism::fake([
'This ticket is about a billing issue.',
]);
With the fake in place, your agent, tools, and middleware all execute their real logic — only the external HTTP call is intercepted.
What Gets Tested
Agent Prompting and Conversation Context
The first set of tests verifies that the agent receives the correct prompt and that conversation history is passed through properly. Because responses are fixed, assertions on the returned content are stable across every run.
Preventing Accidental AI Calls
preventStrayPrompts() is a safety net that causes a test to fail if an AI call fires in a flow that should never trigger the agent — for example, during basic ticket creation:
Prism::preventStrayPrompts();
// Any unexpected AI call in this flow will now throw
$this->post('/tickets', $payload);
This catches regressions where a refactor accidentally introduces an AI call where none was intended.
Queued Prompts
For background classification jobs, you can assert that a queued prompt is dispatched on a valid submission and stays out of the queue on an invalid one:
Queue::fake();
$this->post('/tickets', $validPayload);
Queue::assertPushed(TicketClassifier::class);
Custom Tools Against Real Database Records
Custom tools are tested directly against real database records seeded in the test. A failing test in this episode caught a factory mismatch live — exactly the kind of regression a test suite is supposed to surface.
Feature Testing the Chat Endpoint
The chat endpoint is covered for authentication, request validation, and correct agent interaction, all without touching OpenAI.
Vector Store and Knowledge Base
Store creation, document uploads, and embedding generation are all faked, letting you assert the full knowledge-base seeding flow without any external calls.
The Result
All 12 AI tests pass, run in seconds, and never touch an external API. You can run them on every commit without worrying about cost or flakiness.
Key Takeaways
- The Laravel AI SDK ships a faking system that works just like
Mail::fake()orQueue::fake(). preventStrayPrompts()guards flows that should never trigger an AI call.- Queued AI jobs can be asserted with
Queue::fake()the same way as any other job. - Custom tools should be tested against real seeded records to catch factory mismatches early.
- Feature tests cover auth, validation, and agent interaction without any API cost.
- Deterministic faked responses make assertions reliable across every CI run.
What's Next
The next episode moves into security — protecting the agent against prompt injection by screening every incoming message with a local LLM before it reaches OpenAI, with zero API cost on blocked requests.
📺 Watch Episode 10 on YouTube | ⭐ GitHub Repository
Source: Laravel News — Ship AI with Laravel: Test Your AI System with Zero API Calls