{"id":38487241,"url":"https://github.com/eyo-chen/gofacto","last_synced_at":"2026-01-18T08:23:06.056Z","repository":{"id":245677348,"uuid":"818942075","full_name":"eyo-chen/gofacto","owner":"eyo-chen","description":"A strongly-typed and user-friendly factory library for Go","archived":false,"fork":false,"pushed_at":"2024-12-15T10:19:14.000Z","size":218,"stargazers_count":30,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-17T16:43:06.327Z","etag":null,"topics":["factory","go","golang-library","intergration-test","mockdata","testing","testing-tools"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eyo-chen.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-23T10:12:10.000Z","updated_at":"2025-11-11T22:05:50.000Z","dependencies_parsed_at":"2024-08-09T13:04:18.238Z","dependency_job_id":"c4e6b810-071a-45e3-a186-cdf144e6020b","html_url":"https://github.com/eyo-chen/gofacto","commit_stats":null,"previous_names":["eyo-chen/gofacto"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/eyo-chen/gofacto","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eyo-chen%2Fgofacto","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eyo-chen%2Fgofacto/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eyo-chen%2Fgofacto/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eyo-chen%2Fgofacto/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eyo-chen","download_url":"https://codeload.github.com/eyo-chen/gofacto/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eyo-chen%2Fgofacto/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28534143,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"online","status_checked_at":"2026-01-18T02:00:07.578Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["factory","go","golang-library","intergration-test","mockdata","testing","testing-tools"],"created_at":"2026-01-17T05:37:08.884Z","updated_at":"2026-01-18T08:23:06.035Z","avatar_url":"https://github.com/eyo-chen.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Go Reference](https://pkg.go.dev/badge/github.com/eyo-chen/gofacto.svg)](https://pkg.go.dev/github.com/eyo-chen/gofacto)\n[![Go Report Card](https://goreportcard.com/badge/github.com/eyo-chen/gofacto)](https://goreportcard.com/report/github.com/eyo-chen/gofacto)\n[![Coverage Status](https://coveralls.io/repos/github/eyo-chen/gofacto/badge.svg?branch=main)](https://coveralls.io/github/eyo-chen/gofacto?branch=main)\n\n# gofacto\n\ngofacto is a strongly-typed and user-friendly factory library for Go, designed to simplify the creation of mock data. It offers:\n\n- Intuitive and straightforward usage\n- Strong typing and type safety\n- Flexible data customization\n- Support for various databases and ORMs\n- Basic and multi-level association relationship support\n\n\u0026nbsp;\n\n# Installation\n```bash\ngo get github.com/eyo-chen/gofacto\n```\n\n\u0026nbsp;\n\n# Quick Start\nYou can find more examples in the [examples](https://github.com/eyo-chen/gofacto/tree/main/examples) folder.\n\nLet's consider two structs: `Customer` and `Order`. `Order` struct has a foreign key `CustomerID` because a customer can have many orders.\n```go\ntype Customer struct {\n    ID      int\n    Gender  Gender     // custom defined type\n    Name    string\n    Email   *string\n    Phone   string\n}\n\ntype Order struct {\n    ID          int\n    CustomerID  int       `gofacto:\"foreignKey,struct:Customer\"`\n    OrderDate   time.Time\n    Amount      float64\n}\n\n// Init a Customer factory\ncustomerFactory := gofacto.New(Customer{}).\n                           WithDB(mysqlf.NewConfig(db)) // Assuming db is a database connection\n\n// Create and insert a customer\ncustomer, err := customerFactory.Build(ctx).Insert()\n\n// Create and insert two female customers\ncustomers, err := customerFactory.BuildList(ctx, 2).\n                                  Overwrite(Customer{Gender: Female}).\n                                  Insert()\n// customers[0].Gender == Female\n// customers[1].Gender == Female\n\n// Init a Order factory\norderFactory := gofacto.New(Order{}).\n                        WithDB(mysqlf.NewConfig(db))\n\n// Create and insert an order with one customer\nc := Customer{}\norder, err := orderFactory.Build(ctx).\n                           WithOne(\u0026c).\n                           Insert()\n// order.CustomerID == c.ID\n\n// Create and insert two orders with two customers\nc1, c2 := Customer{}, Customer{}\norders, err := orderFactory.BuildList(ctx, 2).\n                            WithMany([]interface{}{\u0026c1, \u0026c2}).\n                            Insert()\n// orders[0].CustomerID == c1.ID\n// orders[1].CustomerID == c2.ID\n```\nNote: All fields in the returned struct are populated with non-zero values, and `ID` field is auto-incremented by the database.\n\n\u0026nbsp;\n\n# Usage\n### Initialize\nUse `New` to initialize the factory by passing the struct you want to create mock data for.\n```go\nfactory := gofacto.New(Order{})\n```\n\n### Build \u0026 BuildList\nUse `Build` to create a single value, and `BuildList` to create a list of values.\n```go\norder, err := factory.Build(ctx).Get()\norders, err := factory.BuildList(ctx, 2).Get()\n```\n`Get` method returns the struct(s) without inserting them into the database. All fields are populated with non-zero values.\n\n### Insert\nUse `Insert` to insert values into the database.\u003cbr\u003e\n`Insert` method inserts the struct into the database and returns the struct with `ID` field populated with the auto-incremented value.\u003cbr\u003e\n```go\norder, err := factory.Build(ctx).Insert()\norders, err := factory.BuildList(ctx, 2).Insert()\n```\nFind out more [examples](https://github.com/eyo-chen/gofacto/blob/main/examples/basic_test.go).\n\n### Overwrite\nUse `Overwrite` to set specific fields.\u003cbr\u003e\nThe fields in the struct will be used to overwrite the fields in the generated struct.\n```go\norder, err := factory.Build(ctx).Overwrite(Order{Amount: 100}).Insert()\n// order.Amount == 100\n```\n\nWhen building a list of values, `Overwrite` is used to overwrite all the list of values, and `Overwrites` is used to overwrite each value in the list of values.\n```go\norders, err := factory.BuildList(ctx, 2).Overwrite(Order{Amount: 100}).Insert()\n// orders[0].Amount == 100\n// orders[1].Amount == 100\n\norders, err := factory.BuildList(ctx, 2).Overwrites(Order{Amount: 100}, Order{Amount: 200}).Insert()\n// orders[0].Amount == 100\n// orders[1].Amount == 200\n```\n\nNote: Explicit zero values are not overwritten by default. Use `SetZero` or `SetTrait` for this purpose.\n```go\norder, err := factory.Build(ctx).Overwrite(Order{Amount: 0}).Insert()\n// order.Amount != 0\n```\n\nFind out more [examples](https://github.com/eyo-chen/gofacto/blob/main/examples/overwrite_test.go).\n\n\n### SetTrait\nWhen initializing the factory, use `WithTrait` method to set the trait functions and the corresponding keys. Then use `SetTrait` method to apply the trait functions when building the struct.\n```go\nfunc setFemale(c *Customer) {\n  c.Gender = Female\n}\nfactory := gofacto.New(Order{}).\n                   WithTrait(\"female\", setFemale)\n\ncustomer, err := factory.Build(ctx).SetTrait(\"female\").Insert()\n// customer.Gender == Female\n```\n\n\nWhen building a list of values, `SetTrait` is used to apply one trait function to all the list of values, and `SetTraits` is used to apply multiple trait functions to the list of values.\n```go\nfunc setFemale(c *Customer) {\n  c.Gender = Female\n}\nfunc setMale(c *Customer) {\n  c.Gender = Male\n}\nfactory := gofacto.New(Order{}).\n                   WithTrait(\"female\", setFemale).\n                   WithTrait(\"male\", setMale)\n\ncustomers, err := factory.BuildList(ctx, 2).SetTrait(\"female\").Insert()\n// customers[0].Gender == Female\n// customers[1].Gender == Female\n\ncustomers, err := factory.BuildList(ctx, 2).SetTraits(\"female\", \"male\").Insert()\n// customers[0].Gender == Female\n// customers[1].Gender == Male\n```\n\nFind out more [examples](https://github.com/eyo-chen/gofacto/blob/main/examples/settrait_test.go).\n\n### SetZero\nUse `SetZero` to set specific fields to zero values.\u003cbr\u003e\n`SetZero` method with `Build` accepts multiple string as the field names, and the fields will be set to zero values when building the struct.\u003cbr\u003e\n`SetZero` method with `BuildList` accepts an index and multiple string as the field names, and the fields will be set to zero values when building the struct at the index.\n```go\ncustomer, err := factory.Build(ctx).SetZero(\"Email\", \"Phone\").Insert()\n// customer.Email == nil\n// customer.Phone == \"\"\n\ncustomers, err := factory.BuildList(ctx, 2).SetZero(0, \"Email\", \"Phone\").Insert()\n// customers[0].Email == nil\n// customers[0].Phone == \"\"\n// customers[1].Email != nil\n// customers[1].Phone != \"\"\n```\n\nFind out more [examples](https://github.com/eyo-chen/gofacto/blob/main/examples/setzero_test.go).\n\n### WithOne \u0026 WithMany\nWhen there is the associations relationship between the structs, use `WithOne` and `WithMany` methods to build the associated structs.\u003cbr\u003e\nBefore using `WithOne` and `WithMany` methods, make sure setting the correct tag in the struct.\n```go\ntype Order struct {\n  ID          int\n  CustomerID  int       `gofacto:\"foreignKey,struct:Customer\"`\n  OrderDate   time.Time\n  Amount      float64\n}\n```\nYou can find more details about the tag format in [foreignKey tag](#foreignkey-tag).\n\n```go\n// build an order with one customer\nc := Customer{}\norder, err := factory.Build(ctx).WithOne(\u0026c).Insert()\n// order.CustomerID == c.ID\n\n// build two orders with two customers\nc1 := Customer{}\nc2 := Customer{}\norders, err := factory.BuildList(ctx, 2).WithMany([]interface{}{\u0026c1, \u0026c2}).Insert()\n// orders[0].CustomerID == c1.ID\n// orders[1].CustomerID == c2.ID\n\n// build an order with only one customer\nc1 := Customer{}\norders, err := factory.BuildList(ctx, 2).WithOne(\u0026c1).Insert()\n// orders[0].CustomerID == c1.ID\n// orders[1].CustomerID == c1.ID\n```\n\nIf there are multiple level association relationships, both `WithOne` and `WithMany` methods can also come in handy.\u003cbr\u003e\nSuppose we have a following schema:\n```go\ntype Expense struct {\n\tID         int\n\tUserID     int `gofacto:\"foreignKey,struct:User\"`\n\tCategoryID int `gofacto:\"foreignKey,struct:Category,table:categories\"`\n}\n\ntype Category struct {\n\tID     int\n\tUserID int `gofacto:\"foreignKey,struct:User\"`\n}\n\ntype User struct {\n\tID int\n}\n```\n\nWe can build the `Expense` struct with the associated `User` and `Category` structs by using `WithOne` and `WithMany` methods.\n```go\n// build one expense with one user and one category\nuser := User{}\ncategory := Category{}\nexpense, err := factory.Build(ctx).WithOne(\u0026user).WithOne(\u0026category).Insert()\n// expense.UserID == user.ID\n// expense.CategoryID == category.ID\n// category.UserID == user.ID\n\n// build two expenses with two users and two categories\nuser1 := User{}\nuser2 := User{}\ncategory1 := Category{}\ncategory2 := Category{}\nexpenses, err := factory.BuildList(ctx, 2).WithMany([]interface{}{\u0026user1, \u0026user2}).WithMany([]interface{}{\u0026category1, \u0026category2}).Insert()\n// expenses[0].UserID == user1.ID\n// expenses[0].CategoryID == category1.ID\n// expenses[1].UserID == user2.ID\n// expenses[1].CategoryID == category2.ID\n// category1.UserID == user1.ID\n// category2.UserID == user2.ID\n```\n\nThis is one of the most powerful features of gofacto, it helps us easily build the structs with the complex associations relationships as long as setting the correct tags in the struct.\u003cbr\u003e\n\nFind out more [examples](https://github.com/eyo-chen/gofacto/blob/main/examples/association_test.go).\n\n\n\u003cdetails\u003e\n    \u003csummary\u003eBest Practice to use \u003ccode\u003eWithOne\u003c/code\u003e \u0026 \u003ccode\u003eWithMany\u003c/code\u003e\u003c/summary\u003e\n    \u003cul\u003e\n        \u003cli\u003eMust pass the struct pointer to \u003ccode\u003eWithOne\u003c/code\u003e or \u003ccode\u003eWithMany\u003c/code\u003e\u003c/li\u003e\n        \u003cli\u003eMust pass same type of struct pointer to \u003ccode\u003eWithMany\u003c/code\u003e\u003c/li\u003e\n        \u003cli\u003eDo not pass struct with cyclic dependency\u003c/li\u003e\n    \u003c/ul\u003e\n\n    // Do not do this:\n    type A struct {\n        B_ID int `gofacto:\"foreignKey,struct:B\"`\n    }\n    type B struct {\n        A_ID int `gofacto:\"foreignKey,struct:A\"`\n    }\n\u003c/details\u003e\n\n### Reset\nUse `Reset` method to reset the factory.\n```go\nfactory.Reset()\n```\n`Reset` method is recommended to use when tearing down the test.\n\n\u0026nbsp;\n\n### Set Configurations\n### WithBlueprint\nUse `WithBlueprint` method to set the blueprint function which is a clients defined function to generate the struct values.\n```go\nfunc blueprint(i int) *Order {\n  return \u0026Order{\n    OrderDate: time.Now(),\n    Amount:    100*i,\n  }\n}\nfactory := gofacto.New(Order{}).\n                   WithBlueprint(blueprint)\n```\nWhen configure with blueprint, the blueprint function will be called when building the struct first, then the zero value fields will be set to non-zero values by the factory.\nIt is useful when the clients want to set the default values for the struct.\u003cbr\u003e\n\nThe signature of the blueprint function is following:\u003cbr\u003e\n`type blueprintFunc[T any] func(i int) T`\n\nFind out more [examples](https://github.com/eyo-chen/gofacto/blob/main/examples/blueprint_test.go).\n\n### WithStorageName\nUse `WithStorageName` method to set the storage name.\n```go\nfactory := gofacto.New(Order{}).\n                   WithStorageName(\"orders\")\n```\nThe storage name will be used when inserting the value into the database. \u003cbr\u003e\n\nWhen using SQL databases, the storage name is the table name. \u003cbr\u003e\nWhen using NoSQL databases, the storage name is the collection name. \u003cbr\u003e\n\nIt is optional, the snake case of the struct name(s) will be used if not provided.\u003cbr\u003e\n\n### WithDB\nUse `WithDB` method to set the database connection.\n```go\nfactory := gofacto.New(Order{}).\n                   WithDB(mysqlf.NewConfig(db))\n```\nWhen using raw MySQL, use `mysqlf` package. \u003cbr\u003e\nWhen using raw PostgreSQL, use `postgresf` package. \u003cbr\u003e\nWhen using MongoDB, use `mongof` package. \u003cbr\u003e\nWhen using GORM, use `gormf` package. \u003cbr\u003e\n\n### WithIsSetZeroValue\nUse `WithIsSetZeroValue` method to set if the zero values are set.\n```go\nfactory := gofacto.New(Order{}).\n                   WithIsSetZeroValue(false)\n```\nThe zero values will not be set when building the struct if the flag is set to false. \u003cbr\u003e\n\nIt is optional, it's true by default.\n\n### foreignKey tag\nIn order to build the struct with the associated struct, we need to set the correct tag in the struct to tell gofacto how to build the associated struct.\n\nSuppose we have the following structs:\u003cbr\u003e\n`Project` struct has a foreign key `EmployeeID` to reference to `Employee` struct.\n```go\ntype Project struct {\n  ID          int\n  EmployeeID  int `gofacto:\"foreignKey,struct:Employee,table:employees,field:Employee,refField:OtherID\"`\n  Employee    Employee\n}\n\ntype Employee struct {\n  ID      int\n  OtherID int\n  Name    string\n}\n```\n\nThe format of the tag is following:\u003cbr\u003e\n`gofacto:\"foreignKey,struct:{{structName}},table:{{tableName}},field:{{fieldName}},refField:{{referenceFieldName}}\"`\u003cbr\u003e\n- `foreignKey` is the tag name. It is required.\n- `struct` specifies the name of the associated struct. It is required. In this case, `struct:Employee` indicates that `EmployeeID` is a foreign key to reference to `Employee` struct.\n- `table` specifies the table name of the associated struct. It is optional, the snake case and lower case of the struct name(s) will be used if not provided. In this case, `table:employees` indicates that the table name of `Employee` struct is `employees`. However, we can omit it and gofacto will handle it in this example.\n- `field` specifies which struct field contains the associated data. It is optional, and it's typically used with gorm. In this example, `field:Employee` indicates that the `Employee` field in the `Project` struct will hold the related `Employee` data after the relationship is loaded.\n- `refField` specifies which field to join on in the referenced struct. By default, it joins on the `ID` field, but you can specify a different field. For example, `refField:OtherID` tells gofacto to match `Project.EmployeeID` with `Employee.OtherID` instead of `Employee.ID`.\n\nFind out more [examples](https://github.com/eyo-chen/gofacto/blob/main/examples/association_test.go).\n\n\n### omit tag\nUse `omit` tag in the struct to ignore the field when building the struct.\n```go\ntype Order struct {\n  ID          int\n  CustomerID  int       `gofacto:\"struct:Customer\"`\n  OrderDate   time.Time\n  Amount      float64\n  Ignore      string    `gofacto:\"omit\"`\n}\n```\nThe field `Ignore` will not be set to non-zero values when building the struct.\n\n\u0026nbsp;\n\n# Supported Databases\n### MySQL\nUsing `NewConfig` in `mysqlf` package to configure the database connection.\n```go\nfactory := gofacto.New(Order{}).\n                   WithDB(mysqlf.NewConfig(db))\n```\n`db` is `*sql.DB` connection.\n\nAdd `mysqlf` tag in the struct to specify the column name.\n```go\ntype Order struct {\n  ID          int       `mysqlf:\"id\"`\n  CustomerID  int       `mysqlf:\"customer_id\"`\n  OrderDate   time.Time `mysqlf:\"order_date\"`\n  Amount      float64   `mysqlf:\"amount\"`\n}\n```\nIt is optional to add `mysqlf` tag, the snake case of the field name will be used if not provided.\n\n### PostgreSQL\nUsing `NewConfig` in `postgresf` package to configure the database connection.\n```go\nfactory := gofacto.New(Order{}).\n                   WithDB(postgresf.NewConfig(db))\n```\n`db` is `*sql.DB` connection.\n\nAdd `postgresf` tag in the struct to specify the column name.\n```go\ntype Order struct {\n  ID          int       `postgresf:\"id\"`\n  CustomerID  int       `postgresf:\"customer_id\"`\n  OrderDate   time.Time `postgresf:\"order_date\"`\n  Amount      float64   `postgresf:\"amount\"`\n}\n```\nIt is optional to add `postgresf` tag, the snake case of the field name will be used if not provided.\n\n### MongoDB\nUsing `NewConfig` in `mongof` package to configure the database connection.\n```go\nfactory := gofacto.New(Order{}).\n                   WithDB(mongof.NewConfig(db))\n```\n`db` is `*mongo.Database` connection.\n\nAdd `mongof` tag in the struct to specify the column name.\n```go\ntype Order struct {\n  ID          primitive.ObjectID  `mongof:\"_id\"`\n  CustomerID  primitive.ObjectID  `mongof:\"customer_id\"`\n  OrderDate   time.Time           `mongof:\"order_date\"`\n  Amount      float64             `mongof:\"amount\"`\n}\n```\nIt is optional to add `mongof` tag, the snake case of the field name will be used if not provided.\n\n\u0026nbsp;\n\n# Supported ORMs\n### GORM\nUsing `NewConfig` in `gormf` package to configure the database connection.\n```go\nfactory := gofacto.New(Order{}).\n                   WithDB(gormf.NewConfig(db))\n```\n`db` is `*gorm.DB` connection.\n\nWhen using gorm, we might add the association relationship in the struct.\n```go\ntype Order struct {\n  ID          int\n  Customer    Customer   `gorm:\"foreignKey:CustomerID\"`\n  CustomerID  int        `gofacto:\"foreignKey,struct:Customer,field:Customer\"`\n  OrderDate   time.Time\n  Amount      float64\n}\n```\nIt basically tells gofacto that `CustomerID` is the foreign key that references the `ID` field in the `Customer` struct, and the field `Customer` is the associated field.\n\n\u0026nbsp;\n\n\n# Important Considerations\n1. gofacto assumes the `ID` field is the primary key and auto-incremented by the database.\n\n2. gofacto cannot set the custom type values defined by the clients.\n```go\ntype CustomType string\n\ntype Order struct {\n  ID          int\n  CustomType  CustomType\n  OrderDate   time.Time\n  Amount      float64\n}\n```\nIf the struct has a custom type, gofacto will ignore the field, and leave it as zero value.\u003cbr\u003e\nThe clients need to set the values manually by using blueprint or overwrite if they don't want the zero value.\u003cbr\u003e\n\n\u0026nbsp;\n\n# Acknowledgements\nThis library is inspired by the [factory](https://github.com/nauyey/factory), [fixtory](https://github.com/k-yomo/fixtory), [factory-go](https://github.com/bluele/factory-go), and [gogo-factory](https://github.com/vx416/gogo-factory).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feyo-chen%2Fgofacto","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feyo-chen%2Fgofacto","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feyo-chen%2Fgofacto/lists"}