apps/docs/content/guides/functions/unit-test.mdx
Testing is an essential step in the development process to ensure the correctness, reliability, and performance of your Edge Functions. Because Edge Functions often combine HTTP handling, authentication, database access, and business logic, a good testing strategy gives you fast feedback and high confidence before deploying to production.
In this guide you will learn how to write:
The examples and patterns shown here follow the same approaches used internally by Supabase's Edge Functions team.
Deno ships with a fast, native test runner and excellent mocking utilities in @std/testing. See the official Deno testing documentation for more background.
You can use a realistic Edge Function called process-ticket that calculates the final price of a ticket based on the authenticated user's age (loaded from the profiles table).
Business rules:
0)The function receives a JSON payload with a price field and returns { result: finalPrice }.
This example demonstrates common real-world requirements:
withSupabasesupabase/
├── functions/
│ ├── _shared/
│ │ └── types.ts # Database types
│ ├── process-ticket/
│ │ ├── index.ts # Edge Function (uses withSupabase)
│ │ └── pricing.ts # Pure business logic (co-located)
│ └── tests/
│ ├── utils/
│ │ └── supabase_env.ts # Test helpers (env + JWT)
│ └── process-ticket/
│ ├── pricing.test.ts # Unit tests for pricing
│ └── index.test.ts # Integration tests with fetch mocking
├── config.toml
└── deno.json
In this reference implementation the pricing logic lives inside the function folder
process-ticket/pricing.ts. You can also move it to _shared/ if you want to reuse it across
multiple functions.
See the Development Environment and Managing dependencies guides for recommended deno.json and editor setup.
The pricing rules are pure functions with no side effects, so they are perfect candidates for fast, isolated unit tests.
<$CodeSample path="/edge-functions/supabase/functions/unit-testing/process-ticket/pricing.ts" title="Testing pure business logic | Implementation" meta="supabase/functions/process-ticket/pricing.ts" language="typescript" />
The reference implementation uses the BDD-style API from @std/testing/bdd:
<$CodeSample path="/edge-functions/supabase/functions/unit-testing/tests/process-ticket/pricing.test.ts" title="Testing pure business logic | Unit-Test" meta="supabase/functions/tests/process-ticket/pricing.test.ts" language="typescript" />
Run the unit tests:
deno test supabase/functions/tests/process-ticket/pricing.test.ts
These tests run in milliseconds and give you immediate safety when changing discount rules.
The reference implementation uses a pattern: mocking globalThis.fetch to intercept the Supabase REST calls made by the Edge Function. This approach requires zero changes to your production code for testability.
<$CodeSample path="/edge-functions/supabase/functions/unit-testing/process-ticket/index.ts" title="Testing the full Edge Function | Implementation" meta="supabase/functions/process-ticket/index.ts" language="typescript" />
Key points:
withSupabase helper from @supabase/serverctx.supabase clientpricing.tsThis helper sets up a mock Supabase environment and generates valid RS256 JWTs for authenticated requests:
<$CodeSample path="/edge-functions/supabase/functions/unit-testing/tests/utils/supabase_env.ts" title="Testing the full Edge Function | Unit-Test Utils" meta="supabase/functions/tests/utils/supabase_env.ts" language="typescript" />
<$CodeSample path="/edge-functions/supabase/functions/unit-testing/tests/process-ticket/index.test.ts" title="Testing the full Edge Function | Unit-Test" meta="supabase/functions/tests/process-ticket/index.test.ts" language="typescript" />
Run the integration tests:
deno test supabase/functions/tests/process-ticket/index.test.ts --allow-env
This guide uses fetch() mock to demonstrate the following benefits:
This pattern fits great in higher-level helpers that you can control inner code, like withSupabase.
Add to your deno.json:
<$CodeSample path="/edge-functions/supabase/functions/unit-testing/deno.json" title="deno.json file" meta="supabase/deno.json" language="json" lines={[[1,1], [6,-1]]} />
Then:
deno task test
withSupabase + typed Database for clean, authenticated accessfetch boundary for integration tests when you don't want to modify production code@std/testing/bdd + @std/testing/mock for expressive, maintainable testswithSupabase and @supabase/server