{"id":13186,"library":"fishery","title":"Fishery Test Data Factories","description":"Fishery is a JavaScript and TypeScript library designed to streamline the creation of test data objects, heavily inspired by the Ruby `factory_bot` gem. It simplifies the process of generating complex objects with sensible default values, while allowing for easy overrides to suit specific test cases. The library is currently at version 2.4.0 and maintains an active release cadence, with multiple minor and patch updates rolled out over the past year, indicating consistent development and bug fixes. Its core differentiator lies in its strong TypeScript support, providing comprehensive type-checking during factory definition and object instantiation. This ensures type safety and data validity within testing environments, making it a robust choice for projects utilizing TypeScript. It supports both synchronous `build` operations and asynchronous `create` operations, enabling integration with database or other async data persistence layers.","status":"active","version":"2.4.0","language":"javascript","source_language":"en","source_url":"https://github.com/thoughtbot/fishery","tags":["javascript","factories","testing","typescript","factory_bot","factorybot","mock","test data"],"install":[{"cmd":"npm install fishery","lang":"bash","label":"npm"},{"cmd":"yarn add fishery","lang":"bash","label":"yarn"},{"cmd":"pnpm add fishery","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Used internally for deep merging of parameters when building objects.","package":"lodash.mergewith","optional":false}],"imports":[{"note":"While CommonJS `require` might work in some transpiled environments, `fishery` ships with ES Modules, and `import` is the idiomatic way, especially in TypeScript projects.","wrong":"const { Factory } = require('fishery');","symbol":"Factory","correct":"import { Factory } from 'fishery';"},{"note":"This is a TypeScript type, so `import type` is the correct and recommended syntax for clarity and to ensure it's stripped during compilation. It was explicitly exported starting from v2.3.1 to resolve TypeScript errors.","wrong":"import { DeepPartialObject } from 'fishery';","symbol":"DeepPartialObject","correct":"import type { DeepPartialObject } from 'fishery';"},{"note":"`define` is a static method of the `Factory` class, not a direct export. You must import `Factory` and then call `Factory.define`.","wrong":"import { define } from 'fishery';","symbol":"define","correct":"import { Factory } from 'fishery';\nFactory.define(...);"}],"quickstart":{"code":"import { Factory } from 'fishery';\n\ninterface Post {\n  id: number;\n  title: string;\n  content: string;\n}\n\ninterface User {\n  id: number;\n  name: string;\n  email: string;\n  address: { city: string; state: string; country: string };\n  posts: Post[];\n}\n\n// A dummy post factory for demonstration\nconst postFactory = Factory.define<Post>(({ sequence }) => ({\n  id: sequence,\n  title: `Post ${sequence}`,\n  content: `Content for post ${sequence}`,\n}));\n\nconst userFactory = Factory.define<User>(({ sequence }) => ({\n  id: sequence,\n  name: 'Default User',\n  email: `user-${sequence}@example.com`,\n  address: { city: 'Austin', state: 'TX', country: 'USA' },\n  posts: postFactory.buildList(2),\n}));\n\n// Build a user with some overrides\nconst user = userFactory.build({\n  name: 'Susan Smith',\n  address: { city: 'El Paso' },\n  email: 'susan.smith@example.com',\n});\n\nconsole.log(user.name); // Susan Smith\nconsole.log(user.address.city); // El Paso\nconsole.log(user.address.state); // TX (from factory default)\nconsole.log(user.posts.length); // 2\n\n// Example of creating multiple users\nconst users = userFactory.buildList(3, { address: { country: 'Canada' } });\nconsole.log(users[0].address.country); // Canada\nconsole.log(users[1].email); // user-2@example.com (sequence increments)\n","lang":"typescript","description":"This example demonstrates how to define a basic `User` factory and a nested `Post` factory. It shows synchronous object building (`build` and `buildList`), parameter overrides, and how default values are merged with provided parameters, including the use of `sequence` for unique IDs."},"warnings":[{"fix":"Refactor factories to have a single `onCreate` hook, or use the `afterCreate` hook if chaining post-creation logic.","message":"In Fishery v2.0.0, the `onCreate` hook was changed to only allow a single definition per factory. If you previously defined multiple `onCreate` hooks for a single factory, only the last one defined would be used. For scenarios requiring multiple post-creation actions, you should now use the `afterCreate` hook (if introduced, or chain logic within the single `onCreate`).","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Upgrade to `fishery@2.2.1` or any subsequent version (e.g., `npm install fishery@latest`).","message":"Version 2.2.0 had potential build issues. It's recommended to skip directly to 2.2.1 or newer to avoid any unexpected behavior related to the package's distribution.","severity":"gotcha","affected_versions":"=2.2.0"},{"fix":"Upgrade to `fishery@2.2.2` or later. If upgrading is not immediately possible, avoid direct mutation of the `params` object; instead, return a new object with desired modifications or use spread syntax to create a new object.","message":"Prior to v2.2.2, directly modifying the `params` object within your factory definition could lead to unintended side effects or inconsistencies in the built objects, as the object might not have been properly cloned before merging.","severity":"gotcha","affected_versions":"<2.2.2"},{"fix":"Upgrade to `fishery@2.4.0` or a newer version to ensure correct handling of `Buffer` objects during parameter merging.","message":"Before v2.4.0, there was a known issue with the merging of `Buffer` objects, which could lead to incorrect or unexpected data in your generated test objects when `Buffer` instances were part of the parameters.","severity":"gotcha","affected_versions":"<2.4.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure that the property `foo` is defined in the `User` interface, or access only properties that are explicitly part of the interface. This is a core benefit of TypeScript, catching type mismatches early.","cause":"Attempting to access a property on a built object that is not defined in the corresponding TypeScript interface for the factory's return type.","error":"Property 'foo' does not exist on type 'User'."},{"fix":"Only pass properties that exist on the `User` interface (or a `DeepPartial` of it) and ensure their types are compatible. If you need to pass data that doesn't become part of the final object, use `transient` parameters via the second argument to `build` (e.g., `userFactory.build({}, { transient: { foo: 'bar' } })`).","cause":"Passing parameters to `factory.build()` or `factory.create()` that include properties not defined in the factory's primary type (`User` in this example), or with incorrect types.","error":"Argument of type '{ foo: string; }' is not assignable to parameter of type 'Partial<User>'."},{"fix":"Ensure your `fishery` package version is `2.3.1` or higher. If you are on an older version and cannot upgrade, you might need to manually define a similar utility type in your project.","cause":"Attempting to import or use the `DeepPartialObject` type in TypeScript environments before it was officially exported, or in versions prior to its introduction as an export.","error":"Cannot find name 'DeepPartialObject'."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":""}