Seeded test data factories with Fishery and Faker: working versions (tested 2026-10-15)
Build typed test data with Fishery factories backed by seeded @faker-js/faker v10, covering sequences, param overrides, traits, associations, transient params and deterministic output.
passed4 passed · 0 failed2026-10-15 17:10 UTC- Status
- passed
- Last passed
- 2026-10-15 17:10 UTC
- Tests
- 4 / 4
- Language
- TypeScript
- Runtime
- node v22.23.3
pinned versions4
fishery@2.4.0@faker-js/faker@10.6.0@types/node@26.6.5tsx@4.23.15
run it
npm install --no-audit --no-fund --ignore-scripts=false npm test
test environment
node v22.23.3 linux 6.17.0-1022-azure x64 runner: github-actions 38775053802
The code
Exactly the files that passed. Your agent can pull them with get_recipe("faker-fishery-seeded-factories") (install), or see them on GitHub.
package.json
{
"name": "faker-fishery-seeded-factories",
"private": true,
"type": "module",
"scripts": {
"test": "node --import tsx --test test/*.test.ts"
},
"dependencies": {
"fishery": "2.4.0",
"@faker-js/faker": "10.6.0"
},
"devDependencies": {
"@types/node": "26.6.5",
"tsx": "4.23.15"
}
}
src/factories.ts
import { Factory } from "fishery";
import { faker } from "@faker-js/faker";
export type User = { id: number; name: string; email: string; role: "member" | "admin"; createdAt: Date };
export type Post = { id: number; title: string; author: User; tags: string[] };
const REF_DATE = new Date("2026-01-01T00:00:00Z");
class UserFactory extends Factory<User, { domain: string }> {
admin() {
return this.params({ role: "admin" });
}
}
export const userFactory = UserFactory.define(({ sequence, transientParams }) => {
const first = faker.person.firstName();
const last = faker.person.lastName();
return {
id: sequence,
name: `${first} ${last}`,
email: faker.internet.email({ firstName: first, lastName: last, provider: transientParams.domain ?? "example.test" }).toLowerCase(),
role: "member",
createdAt: faker.date.past({ years: 1, refDate: REF_DATE }),
};
});
export const postFactory = Factory.define<Post>(({ sequence, associations }) => ({
id: sequence,
title: faker.lorem.sentence({ min: 3, max: 6 }),
author: associations.author ?? userFactory.build(),
tags: faker.helpers.arrayElements(["ts", "node", "testing", "mcp", "api"], 2),
}));
/** Reset faker and factory sequences so every test starts from the same data. */
export function resetData(seed = 42) {
faker.seed(seed);
userFactory.rewindSequence();
postFactory.rewindSequence();
}
test/factories.test.ts
import { test, beforeEach } from "node:test";
import assert from "node:assert/strict";
import { userFactory, postFactory, resetData } from "../src/factories.ts";
beforeEach(() => resetData());
test("same seed produces identical data", () => {
const first = userFactory.buildList(3);
resetData();
const second = userFactory.buildList(3);
assert.deepEqual(first, second);
assert.deepEqual(first.map((u) => u.id), [1, 2, 3]);
});
test("different seeds produce different data", () => {
const a = userFactory.build();
resetData(7);
const b = userFactory.build();
assert.notEqual(a.name, b.name);
});
test("params, traits and transient params", () => {
const admin = userFactory.admin().build({ name: "Root User" }, { transient: { domain: "corp.test" } });
assert.equal(admin.role, "admin");
assert.equal(admin.name, "Root User");
assert.match(admin.email, /@corp\.test$/);
assert.ok(admin.createdAt < new Date("2026-01-01T00:00:00Z"));
});
test("associations reuse a given author", () => {
const author = userFactory.build({ name: "Ada Lovelace" });
const posts = postFactory.buildList(2, {}, { associations: { author } });
// Fishery merges associations into a fresh object, so compare by value.
assert.deepEqual(posts[0].author, author);
assert.equal(posts[1].author.name, "Ada Lovelace");
assert.equal(posts[0].tags.length, 2);
assert.notEqual(posts[0].id, posts[1].id);
});
Connect to ProvenPin
Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.
terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp
~/.cursor/mcp.json
{ "mcpServers": { "provenpin": { "url": "https://mcp.provenpin.com/mcp" } } }.vscode/mcp.json
{ "servers": { "provenpin": { "type": "http", "url": "https://mcp.provenpin.com/mcp" } } }~/.codeium/windsurf/mcp_config.json
{ "mcpServers": { "provenpin": { "serverUrl": "https://mcp.provenpin.com/mcp" } } }MCP settings
{ "mcpServers": { "provenpin": { "type": "streamableHttp", "url": "https://mcp.provenpin.com/mcp" } } }Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.