Skip to content

mikemajesty/zod-mock-schema

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

59 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Zod Mock Schema

npm version License TypeScript Ready

Simple, type-safe mock data generator for Zod schemas with built-in Brazilian format support πŸ‡§πŸ‡·

A developer-friendly, class-based utility for generating realistic test data from Zod schemas. Perfect for testing, prototyping, and fixtures β€” with zero configuration and maximum type safety.

✨ Why Choose This Library?

🎯 Simplicity First

  • Clean class-based API β€” instantiate once, generate many times
  • Zero configuration β€” works out of the box with any Zod schema
  • Type-safe overrides β€” full TypeScript intellisense and validation
  • Intuitive seeding β€” mock.seed(123) for deterministic tests

πŸ‡§πŸ‡· Brazilian Format Support

  • CPF, CNPJ, RG β€” built-in Brazilian document formats
  • CEP β€” postal code generation
  • Phone BR β€” Brazilian phone numbers
  • Zero dependencies β€” no extra libraries needed

⚑ Developer Experience

  • Faker.js integration β€” realistic, locale-aware fake data
  • Custom Faker injection β€” use different locales per test
  • Batch generation β€” generateMany() for multiple mocks
  • Full Zod v4 support β€” Union, Intersection, Record, Lazy, Pipe, and more

πŸ“¦ Installation

# npm
npm install @mikemajesty/zod-mock-schema zod @faker-js/faker

# yarn
yarn add @mikemajesty/zod-mock-schema zod @faker-js/faker

# pnpm
pnpm add @mikemajesty/zod-mock-schema zod @faker-js/faker

⚠️ Important: zod and @faker-js/faker are peer dependencies and must be installed separately.


πŸš€ Quick Start

import { z } from 'zod';
import { ZodMockSchema } from '@mikemajesty/zod-mock-schema';

const userSchema = z.object({
  id: z.string().uuid(),
  name: z.string(),
  email: z.string().email(),
  age: z.number().int().min(18).max(99),
  isActive: z.boolean(),
  createdAt: z.date(),
});

const userMock = new ZodMockSchema(userSchema);

console.log(userMock.generate());

🎭 Type Inference with Generics

The library supports generic type inference, allowing you to specify the exact type you want:

Using z.infer (Recommended)

The best practice is to derive the type directly from the schema using z.infer:

const userSchema = z.object({
  id: z.string().uuid(),
  name: z.string(),
  email: z.string().email(),
  age: z.number().int().min(18).max(99),
  isActive: z.boolean(),
  createdAt: z.date(),
});

// βœ… Best practice: infer type from schema
type User = z.infer<typeof userSchema>;

const userMock = new ZodMockSchema(userSchema);

// Type is automatically inferred as User
const user = userMock.generate<User>();

Type Inference with Classes/Entities

Perfect for testing with ORM entities or class instances:

class UserEntity {
  id: string;
  name: string;
  email: string;
  age: number;
  isActive: boolean;
  createdAt: Date;
  
  get isAdult() {
    return this.age >= 18;
  }
}

// Create schema that matches entity structure
const userSchema = z.object({
  id: z.string().uuid(),
  name: z.string(),
  email: z.string().email(),
  age: z.number().int().min(18).max(99),
  isActive: z.boolean(),
  createdAt: z.date(),
});

const userMock = new ZodMockSchema(userSchema);

// Generate mock data typed as UserEntity
const user = userMock.generate<UserEntity>();
// user.id, user.name, etc. are properly typed

Type Inference with generateMany

type User = z.infer<typeof userSchema>;

// Generate array of typed entities
const users = userMock.generateMany<User>(5);
// users is User[]

// With overrides
const activeUsers = userMock.generateMany<User>(3, {
  overrides: { isActive: true }
});

πŸ”§ Basic Usage

1. Simple Mock

const productSchema = z.object({
  id: z.number(),
  title: z.string(),
  price: z.number().positive(),
  inStock: z.boolean(),
  tags: z.array(z.string()),
});

const productMock = new ZodMockSchema(productSchema);
productMock.generate();

2. Override Properties

userMock.generate({
  overrides: {
    name: 'Alice Johnson',
    age: 25,
    email: 'alice@company.com',
    createdAt: new Date('2023-01-01'),
  }
});

3. Generate Multiple Items

userMock.generateMany(3, {
  overrides: { department: 'Engineering' }
});

πŸ‡§πŸ‡· Brazilian Formats

Generate valid Brazilian documents and identifiers with zero configuration:

import { ZodMockSchema, BrazilianFormat } from '@mikemajesty/zod-mock-schema';

const userSchema = z.object({
  cpf: z.string().meta({ format: 'cpf' }),      // 11-digit CPF
  cnpj: z.string().meta({ format: 'cnpj' }),   // 14-digit CNPJ
  rg: z.string().meta({ format: 'rg' }),       // Brazilian ID
  phone: z.string().meta({ format: 'phoneBR' }), // BR phone number
  cep: z.string().meta({ format: 'cep' }),     // Postal code
});

const mock = new ZodMockSchema(userSchema);
const user = mock.generate();
// {
//   cpf: "52998224725",
//   cnpj: "60676960000106",
//   rg: "238192611",
//   phone: "11987654321",
//   cep: "01001000"
// }

// TypeScript support for format validation
const format: BrazilianFormat = 'cpf'; // Type-safe!

### Why This Matters

Brazilian formats require specific validation rules that generic mock generators don't understand. This library provides:

- βœ… **Pre-validated samples** β€” all generated values pass real validation
- βœ… **No external APIs** β€” works offline, no rate limits
- βœ… **Deterministic with seeds** β€” same seed = same CPF/CNPJ
- βœ… **Works in arrays and nested objects** β€” generate multiple documents easily

```ts
// Generate multiple users with valid Brazilian docs
const users = mock.generateMany(10);
users.forEach(u => console.log(u.cpf)); // All valid CPFs

🧠 Full Zod Schema Support

Supports all Zod types including advanced patterns:

const complexSchema = z.object({
  status: z.union([z.literal('active'), z.literal('inactive'), z.literal('pending')]),
  userWithRole: z.object({ name: z.string() }).and(z.object({ role: z.string() })),
  metadata: z.record(z.string()),
  optionalField: z.string().optional(),
  nullableField: z.string().nullable(),
  tags: z.array(z.string()).min(1).max(5),
  score: z.number().default(0),
  nested: z.lazy(() => complexSchema.optional()),
});

const complexMock = new ZodMockSchema(complexSchema);
complexMock.generate();

πŸ›’ E-commerce Example

const orderSchema = z.object({
  id: z.string().uuid(),
  customerId: z.string().uuid(),
  items: z.array(z.object({
    productId: z.string().uuid(),
    quantity: z.number().int().positive(),
    price: z.number().positive(),
  })),
  total: z.number().positive(),
  status: z.enum(['pending', 'processing', 'shipped', 'delivered']),
  createdAt: z.date(),
  metadata: z.record(z.any()).optional(),
});

const orderMock = new ZodMockSchema(orderSchema);

orderMock.generateMany(5, {
  overrides: {
    status: 'processing',
    total: 1399.97,
  }
});

🏭 Factory Pattern

export class UserFactory {
  private mock = new ZodMockSchema(userSchema);

  create(overrides?: Partial<User>) {
    return this.mock.generate({ overrides });
  }

  createMany(count: number, options?: MockManyOptions<User>) {
    return this.mock.generateMany(count, options);
  }

  createAdmins(count: number) {
    return this.mock.generateMany(count, {
      overrides: { role: 'admin' }
    });
  }
}

πŸ§ͺ Testing Patterns

Deterministic Tests

const userMock = new ZodMockSchema(userSchema);
userMock.seed(123);
const user = userMock.generate();

Using Faker Directly

You can use faker in overrides to generate custom values:

import { ZodMockSchema } from '@mikemajesty/zod-mock-schema';
import { faker } from '@faker-js/faker';

// Use faker directly for custom values
const user = userMock.generate({
  overrides: {
    name: faker.person.fullName(),
    email: faker.internet.email(),
    bio: faker.lorem.paragraph(),
  }
});

Custom Faker Instance

Inject a custom Faker instance with different locales or configurations:

import { Faker, pt_BR } from '@faker-js/faker';

const customFaker = new Faker({ locale: pt_BR });
const user = userMock.generate({ faker: customFaker });

Parallel Tests with Isolated Faker Instances

import { Faker, en, es } from '@faker-js/faker';

test('parallel test 1', () => {
  const faker1 = new Faker({ locale: en });
  faker1.seed(100);
  const user = userMock.generate({ faker: faker1 });
});

test('parallel test 2', () => {
  const faker2 = new Faker({ locale: es });
  faker2.seed(200);
  const user = userMock.generate({ faker: faker2 });
});

Integration Testing

describe('User Service', () => {
  const userMock = new ZodMockSchema(userSchema);

  test('should create multiple unique users', () => {
    const users = userMock.generateMany(5);

    const emails = users.map(u => u.email);
    expect(new Set(emails).size).toBe(5);
  });
});

πŸ“˜ API Reference

new ZodMockSchema(schema)

Creates a mock generator for the given Zod schema.

Methods

generate(options?: MockOptions<T>): T

Generates a single mock object.

generateMany(count: number, options?: MockManyOptions<T>): T[]

Generates multiple mock objects.

Exported Types

MockOptions<T>

Configuration options for generating a single mock object.

  • overrides?: Partial<T> β€” Override specific properties
  • faker?: Faker β€” Custom Faker instance for localization

MockManyOptions<T>

Extends MockOptions<T> for batch generation.

BrazilianFormat

Type-safe union of Brazilian format identifiers:

type BrazilianFormat = 'cpf' | 'cnpj' | 'rg' | 'phoneBR' | 'cep';

πŸ”„ Supported Zod Types

βœ“ String Β· Number Β· Boolean Β· Date Β· Array
βœ“ Object Β· Union Β· Intersection Β· Enum
βœ“ Record Β· Optional Β· Nullable Β· Default
βœ“ Lazy Β· Literal Β· Any Β· Unknown
βœ“ Void Β· Null Β· Pipe


🧹 Best Practices

Keep It Simple

// βœ… Good: Reuse instances
const userMock = new ZodMockSchema(userSchema);
const user1 = userMock.generate();
const user2 = userMock.generate();

// ❌ Avoid: Creating new instances every time
const user1 = new ZodMockSchema(userSchema).generate();
const user2 = new ZodMockSchema(userSchema).generate();

Use Overrides for Business Logic

// βœ… Good: Override specific fields
userMock.generate({ overrides: { role: 'admin', status: 'active' } });

// ❌ Avoid: Manually modifying generated data
const user = userMock.generate();
user.role = 'admin'; // Bypasses Zod validation

Centralize Test Factories

// βœ… Good: Single source of truth
export const UserFactory = new ZodMockSchema(userSchema);

// In tests:
import { UserFactory } from './factories';
const admin = UserFactory.generate({ overrides: { role: 'admin' } });

Use Seeds for Deterministic Tests

// βœ… Good: Reproducible tests
test('user creation', () => {
  userMock.seed(12345);
  const user = userMock.generate();
  expect(user.name).toBe('Alice'); // Always the same with same seed
});

πŸ“„ License

MIT Β© Mike Majesty

About

Generate realistic mock data from Zod schemas with Faker.js integration - Perfect for testing and prototyping

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors