- module name:
github.com/akm/go-fixtures
- package name:
fixtures
fixtures
package simplifies database operations in tests using models based on Functional Options Pattern. It integrates with GORM for object manipulation but remains agnostic to the specific models you use. Test fixtures can be defined directly in Go code.
fixtures
works seamlessly with models designed for GORM, making it straightforward to create and manage fixtures.
Even if you use sqlc to generate models, fixtures is compatible. The structure of sqlc-generated models is similar to GORM models, making the integration easy. For example:
Even if you're using another ORM or none at all, fixtures allows you to define plain fixture models. Feel free to reach out if you encounter any issues.
go get github.com/akm/go-fixtures
- Define fixture models.
- Add functional
Option
s types for the models. - Create a
Fixtures
struct for each model. - Use the defined fixtures in your tests.
If you already have a model, you can embed it. Otherwise, define a new model or skip this step if it's unnecessary.
type Article struct {
ID int
CreatedAt time.Time
UpdatedAt time.Time
AuthorID int
Title string
Url string
}
type Article struct {
models.Article
Author *users.User
}
For examples, see:
- examples/models/user.go
- examples/fixtures/users/model.go
- examples/models/article.go
- examples/fixtures/articles/model.go
Define Option types and corresponding functions using the Functional Option Pattern. Refer to Rob Pike's article and Dave Cheney's article.
type Option = func(*Article)
func Title(v string) Option { return func(a *Article) { a.Title = v } }
func Url(v string) Option { return func(a *Article) { a.Url = v } }
func AuthorID(v int) Option { return func(a *Article) { a.AuthorID = v } }
func Author(v *users.User) Option {
return func(a *Article) {
a.Author = v
if v != nil {
a.AuthorID = v.ID
} else {
a.AuthorID = 0
}
}
}
You can instantiate models using fixtures.New[T any]
or fixtures.NewWithDefaults[T any]
.
type Fixtures struct {
*fixtures.Fixtures[Article]
Users *users.Fixtures
}
Embed *fixtures.Fixtures
to inherit its methods New
and Get
.
Include related fixture types as fields if fixture model refers other models.
func NewFixtures() *Fixtures {
r := &Fixtures{
Users: users.NewFixtures(),
}
r.Fixtures = fixtures.NewFixtures[Article](r)
return r
}
Define methods to create specific fixture instances:
func (f *Fixtures) NewFiveRules(opts ...Option) *Article {
return fixtures.NewWithDefaults(opts,
Author(f.Users.RobPike()),
Title("Rob Pike's 5 Rules of Programming"),
Url("https://users.ece.utexas.edu/~adnan/pike.html"),
)
}
These methods must:
- Be variadic to accept zero or more
Option
s. - Return a pointer to the model.
func (f *Fixtures) FiveRules(opts ...Option) *Article { return f.Get("FiveRules", opts...) }
This is a fixed form. You can change the method name, but the first argument of f.Get
must match the method name.
For examples, see:
fixtures
uses GORM.
To set up fixtures.DB
, you need to provide a gorm.Dialector
and optionally one or more gorm.Option
s. If you use a specific database (e.g., MySQL), make sure to install the corresponding GORM driver. For instance, for MySQL, run:
go get gorm.io/driver/mysql
Here’s an example of setting up fixtures.DB
:
gormLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags),
logger.Config{SlowThreshold: time.Second, LogLevel: logger.Info},
)
fx := fixtures.NewDB(
mysql.New(mysql.Config{Conn: db}),
&gorm.Config{Logger: gormLogger},
)(t)
To delete all records from specific tables, use fx.DeleteFromTable
. Pass instances of your model with zero-value fields as arguments:
fx.DeleteFromTable(t, &articles.Article{}, &users.User{})
To insert fixture data, create an instance of your Fixtures
struct and call fx.Create
, passing the fixture instances you want to add to the database.
fxArticles := articles.NewFixtures()
fx.Create(t,
fxArticles.FiveRules(),
fxArticles.GoProverbs(),
fxArticles.ABriefIntroduction(),
)
For more information on setting up and using GORM, see Connecting to a Database. You can also refer to examples/tests/example_test.go for a complete implementation.
You can view the test results in GitHub Actions.GitHub Actions.
MIT License