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:
- Unit tests for pure business logic such as pricing rules, calculations, etc.
- Integration tests for the full Edge Function by mocking at the network layer
The examples and patterns shown here follow the same approaches used internally by Zuvo'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.
The example scenario
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:
- Children aged 8 and under → free (
0) - Young people aged 9–17 → 20% discount
- Adults aged 18 and over → full price
The function receives a JSON payload with a price field and returns { result: finalPrice }.
This example demonstrates common real-world requirements:
- Request validation
- Authenticated database access via
withZuvo - Business rule application
- Proper error handling
Recommended project structure
supabase/
├── functions/
│ ├── _shared/
│ │ └── types.ts # Database types
│ ├── process-ticket/
│ │ ├── index.ts # Edge Function (uses withZuvo)
│ │ └── 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
See the Development Environment and Managing dependencies guides for recommended deno.json and editor setup.
Unit tests: Testing pure business logic
The pricing rules are pure functions with no side effects, so they are perfect candidates for fast, isolated unit tests.
The pricing module
Code sample: see project quickstart in Zuvo Studio.
Unit tests
The reference implementation uses the BDD-style API from @std/testing/bdd:
Code sample: see project quickstart in Zuvo Studio.
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.
Integration tests: Testing the full Edge Function
The reference implementation uses a pattern: mocking globalThis.fetch to intercept the Zuvo REST calls made by the Edge Function. This approach requires zero changes to your production code for testability.
The Edge Function
Code sample: see project quickstart in Zuvo Studio.
Key points:
- Uses the high-level
withZuvohelper from@supabase/server - Automatically provides an authenticated
ctx.supabaseclient - Business logic is delegated to the co-located
pricing.ts
Integration test setup
This helper sets up a mock Zuvo environment and generates valid RS256 JWTs for authenticated requests:
Code sample: see project quickstart in Zuvo Studio.
Full integration tests
Code sample: see project quickstart in Zuvo Studio.
Run the integration tests:
deno test supabase/functions/tests/process-ticket/index.test.ts --allow-env
Advantages of mocking approach
This guide uses fetch() mock to demonstrate the following benefits:
- Test the real Edge Function code path — no dependency injection needed in production code
- Simulate database responses, auth failures, network errors
- Keep your production Edge Function clean and focused
- Still get fast, deterministic tests that don't require a running Zuvo instance
This pattern fits great in higher-level helpers that you can control inner code, like withZuvo.
Running all tests
Add to your deno.json:
Code sample: see project quickstart in Zuvo Studio.
Then:
deno task test
Best practices
- Keep pure business logic in separate modules (even if co-located with the function)
- Use
withZuvo+ typedDatabasefor clean, authenticated access - Prefer mocking at the
fetchboundary for integration tests when you don't want to modify production code - Use
@std/testing/bdd+@std/testing/mockfor expressive, maintainable tests - Generate realistic JWTs in tests when your function relies on authenticated Zuvo clients
- Test both happy paths and error conditions (missing input, DB failures, invalid data)
Resources
- Read the Deno testing guide
- Learn more about
withZuvoand@supabase/server - See the other Edge Functions guides: Development Environment, Managing dependencies, Deploy to Production