Skip to content
oRPC
Esc
navigateopen⌘Jpreview
On this page

Testing and Mocking

Testing and mocking are essential for building reliable applications. In this section, we’ll explore how to test your procedures and routers effectively, as well as how to create mock implementations for testing purposes.

Testing

For fast, focused tests, use Server-Side Clients or call your procedures directly with call. This lets you verify validation, middleware, and handler logic without going through HTTP.

import { call } from '@orpc/server'

it('lists planets', async () => {
  await expect(
    call(router.planet.list, { page: 1, size: 10 })
  ).resolves.toEqual([
    { id: '1', name: 'Earth' },
    { id: '2', name: 'Mars' },
  ])
})

Mocking

Use the Implementer to create test-specific versions of a procedure or router. This is useful when one part of your system depends on another procedure, but your test should not execute the real implementation.

import { function implement<TContract extends RouterContract, TInitialContext extends Context = DefaultInitialContext>(contract: TContract, config?: ProcedureConfig): Implementer<TContract, TInitialContext & object>
Turns a contract into an implementer, used to implement the contract's procedures, routers, and middleware with full type safety.
@see{@link https://orpc.dev/docs/contract/implementation#implementer Contract Implementation - Implementer}
implement
} from '@orpc/server'
const
const fakeListPlanet: ImplementedProcedure<DefaultInitialContext & object, object, ZodObject<{
    limit: ZodOptional<ZodNumber>;
    cursor: ZodDefault<ZodNumber>;
}, $strip>, ZodArray<ZodObject<{
    id: ZodNumber;
    name: ZodString;
    description: ZodOptional<ZodString>;
}, $strip>>, object>
fakeListPlanet
=
implement<ImplementedProcedure<{
    headers?: IncomingHttpHeaders;
} & object, object, ZodObject<{
    limit: ZodOptional<ZodNumber>;
    cursor: ZodDefault<ZodNumber>;
}, $strip>, ZodArray<ZodObject<{
    id: ZodNumber;
    name: ZodString;
    description: ZodOptional<ZodString>;
}, $strip>>, object>, DefaultInitialContext>(contract: ImplementedProcedure<{
    headers?: IncomingHttpHeaders;
} & object, object, ZodObject<...>, ZodArray<...>, object>, config?: ProcedureConfig): Implementer<...>
Turns a contract into an implementer, used to implement the contract's procedures, routers, and middleware with full type safety.
@see{@link https://orpc.dev/docs/contract/implementation#implementer Contract Implementation - Implementer}
implement
(
const router: {
    planet: {
        list: ImplementedProcedure<{
            headers?: IncomingHttpHeaders;
        } & object, object, ZodObject<{
            limit: ZodOptional<ZodNumber>;
            cursor: ZodDefault<ZodNumber>;
        }, $strip>, ZodArray<ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>>, object>;
        find: ImplementedProcedure<{
            headers?: IncomingHttpHeaders;
        } & object, object, ZodObject<{
            id: ZodNumber;
        }, $strip>, ZodObject<...>, object>;
        create: ImplementedProcedure<...>;
    };
}
router
.
planet: {
    list: ImplementedProcedure<{
        headers?: IncomingHttpHeaders;
    } & object, object, ZodObject<{
        limit: ZodOptional<ZodNumber>;
        cursor: ZodDefault<ZodNumber>;
    }, $strip>, ZodArray<ZodObject<{
        id: ZodNumber;
        name: ZodString;
        description: ZodOptional<ZodString>;
    }, $strip>>, object>;
    find: ImplementedProcedure<{
        headers?: IncomingHttpHeaders;
    } & object, object, ZodObject<{
        id: ZodNumber;
    }, $strip>, ZodObject<...>, object>;
    create: ImplementedProcedure<...>;
}
planet
.
list: ImplementedProcedure<{
    headers?: IncomingHttpHeaders;
} & object, object, ZodObject<{
    limit: ZodOptional<ZodNumber>;
    cursor: ZodDefault<ZodNumber>;
}, $strip>, ZodArray<ZodObject<{
    id: ZodNumber;
    name: ZodString;
    description: ZodOptional<ZodString>;
}, $strip>>, object>
list
).
ProcedureImplementer<DefaultInitialContext & object, object, ZodObject<{ limit: ZodOptional<ZodNumber>; cursor: ZodDefault<ZodNumber>; }, $strip>, ZodArray<...>, object>['handler'](handler: ProcedureHandler<DefaultInitialContext & object, {
    cursor: number;
    limit?: number | undefined;
}, {
    id: number;
    name: string;
    description?: string | undefined;
}[] | AnyORPCError, object>): ImplementedProcedure<DefaultInitialContext & object, object, ZodObject<{
    limit: ZodOptional<ZodNumber>;
    cursor: ZodDefault<ZodNumber>;
}, $strip>, ZodArray<ZodObject<{
    id: ZodNumber;
    name: ZodString;
    description: ZodOptional<...>;
}, $strip>>, object>
handler
(() => [])

Use fakeListPlanet anywhere your test would normally use the real listPlanet procedure.

Last updated on August 6, 2026

Was this page helpful?