Skip to content
oRPC
Esc
navigateopen⌘Jpreview
On this page

Testing and Mocking

Learn how to test oRPC procedures directly with server-side clients and create mock implementations with the implementer.

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 8, 2026

Was this page helpful?