Testing
Vovk.ts procedures expose an .fn method that calls the handler directly, skipping the HTTP round-trip. This makes unit testing straightforward — no server required.
Setup
Any test runner works (Vitest, Jest, Node.js test runner, etc.). Examples below use Vitest.
Testing with .fn
Given a controller:
src/modules/user/UserController.ts
import { z } from 'zod';
import { procedure, get, post, prefix } from 'vovk';
@prefix('users')
export default class UserController {
@get('{id}')
static getUser = procedure({
params: z.object({ id: z.string() }),
output: z.object({ id: z.string(), name: z.string() }),
}).handle(async ({ vovk }) => {
const { id } = vovk.params();
return { id, name: 'John' };
});
@post()
static createUser = procedure({
body: z.object({ name: z.string() }),
output: z.object({ id: z.string(), name: z.string() }),
}).handle(async ({ vovk }) => {
const { name } = await vovk.body();
return { id: 'new-id', name };
});
}Test it directly:
src/modules/user/UserController.test.ts
import { describe, it, expect } from 'vitest';
import UserController from './UserController';
describe('UserController', () => {
it('gets a user by ID', async () => {
const user = await UserController.getUser.fn({
params: { id: '42' },
});
expect(user).toEqual({ id: '42', name: 'John' });
});
it('creates a user', async () => {
const user = await UserController.createUser.fn({
body: { name: 'Alice' },
});
expect(user).toEqual({ id: 'new-id', name: 'Alice' });
});
});The .fn method runs the full procedure pipeline including validation and decorators, but without HTTP overhead.
Testing Validation
Since procedures validate input, you can test that invalid data is rejected:
src/modules/user/UserController.test.ts
import { describe, it, expect } from 'vitest';
import { HttpException } from 'vovk';
import UserController from './UserController';
describe('UserController validation', () => {
it('rejects invalid body', async () => {
await expect(
UserController.createUser.fn({
body: { name: 123 }, // invalid
})
).rejects.toThrow(HttpException);
});
});Integration Testing with RPC Modules
For end-to-end tests that go through the HTTP layer, use the generated RPC modules against a running dev server:
src/modules/user/UserController.e2e.test.ts
import { describe, it, expect } from 'vitest';
import { UserRPC } from 'vovk-client';
describe('UserController E2E', () => {
it('gets a user via HTTP', async () => {
const user = await UserRPC.getUser({ params: { id: '42' } });
expect(user).toEqual({ id: '42', name: 'John' });
});
});Last updated on