Skip to content
oRPC
Esc
navigateopen⌘Jpreview
On this page

Testing and Mocking

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

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.

Mocking Network Requests

To mock at the network level instead, for example in Storybook stories or browser tests, use the MSW Integration. It turns a contract or router into typed MSW request handlers served through a real fetch handler:

import { createHTTPUtils } from '@orpc/experimental-msw'
import { RPCHandler } from '@orpc/server/fetch'

const mock = createHTTPUtils(router, {
  prefix: '/rpc',
  handler: router => new RPCHandler(router),
})

const handlers = [
  mock.planet.list.handler(() => []),
]

Last updated on August 21, 2026

Was this page helpful?