Gosoline Fixture Loader
While using gosoline you are able to define fixtures directly in code.
Usage
- Enable fixture loading in your
config.dist.yml
File
fixtures:
enabled: true
Make sure to use a custom build tag named
fixtures
Define your fixtures in code while using one of the built in
FixtureWriter
s and defining a slice of[]fixtures.FixtureSet{}
or usefixtures.FixtureSetFactory
orfixtures.FixtureSetsFactory
depending on your use-case. For more details check the/examples/fixtures
Directory or read the short example below.The
fixtures.FixtureSet
interface allows you to define any custom implementation for writing fixture sets to their destination and take control of purging prior writing too. You can however use thefixures.simpleFixtureSet
via thefixtures.NewSimpleFixtureSet
factory func to use a simple yet effective and prebuilt solution. This is the simpleFixtureSet struct definition:
type simpleFixtureSet[T any] struct {
Enabled bool
Purge bool
Writer FixtureWriter
Fixtures NamedFixtures[T]
}
You can easily define multiple fixtures for different destinations in one file, enable/disable them or even enable/disable
purging for each fixtures.FixtureSet
via the fixtures.WithEnabled
and fixtures.WithPurge
fixtures.FixtureSetOption
for the fixtures.NewSimpleFixtureSet
func.
- Currently there are 7 different FixtureWriter implementations for loading fixtures:
Implementation Direct creation Factory for use with fixtures.NewFixtureSetsFactory Blob stores (AWS S3) fixtures.NewBlobFixtureWriter` fixtures.BlobFixtureSetFactory AWS DynamoDB fixtures.NewDynamoDbFixtureWriter` fixtures.DynamoDbFixtureSetFactory KvStore backed by AWS DynamoDB fixtures.DynamoDbKvStoreFixtureWriterFactory` fixtures.DynamoDbKvStoreFixtureSetFactory MySQL (backed by gosoline ORM implementation) fixtures.MysqlOrmFixtureWriterFactory` fixtures.MysqlOrmFixtureSetFactory MySQL (plain columns/values) fixtures.MysqlPlainFixtureWriterFactory` fixtures.MysqlPlainFixtureSetFactory MySQL (sqlx named prepared statements) fixtures.NewMysqlSqlxFixtureWriter` fixtures.MysqlSqlxFixtureSetFactory Redis fixtures.NewRedisFixtureWriter` fixtures.RedisFixtureSetFactory KvStore backed by Redis fixtures.NewRedisKvStoreFixtureWriter` fixtures.RedisKvStoreFixtureSetFactory
Quick Usage
- During the creation of your Application make sure to pass the
WithFixtureSetsFactory
option and provide the group name and a fixture sets factory as arguments of typefixtures.WithFixtureSetsFactory
. Thedefault
group is enabled by default.
func main() {
app := application.Default(
application.WithFixtureSetFactory("default", fixtureSetsFactory),
)
app.Run()
}
For blob stores (when using the BlobFixtureWriterFactory
) you need a configuration entry added:
blob:
blobconfig:
bucket: s3-fixtures-bucket
ID Generation
You can also generate a locally unique identifier for your fixtures via fixtures.AutoNumbered
.
Example with available fixture writers:
func main() {
app := application.Default(
application.WithFixtureSetFactory(fixtureSetsFactory),
)
app.Run()
}
var autoNumbered = fixtures.NewAutoNumberedFrom(2)
func mysqlOrmFixtureSet(ctx context.Context, config cfg.Config, logger log.Logger) (fixtures.FixtureSet, error) {
mysqlMetadata := &db_repo.Metadata{
ModelId: mdl.ModelId{
Name: "orm_fixture_example",
},
}
mysqlOrmWriter, err := fixtures.NewMysqlOrmFixtureWriter(ctx, config, logger, mysqlMetadata)
if err != nil {
return nil, fmt.Errorf("failed to initialize mysql orm writer: %w", err)
}
return fixtures.NewSimpleFixtureSet(fixtures.NamedFixtures[OrmFixtureExample]{
&fixtures.NamedFixture[OrmFixtureExample]{
Name: "foo",
Value: OrmFixtureExample{
Model: db_repo.Model{
Id: autoNumbered.GetNext(),
},
Name: mdl.Box("example"),
},
},
}, mysqlOrmWriter), nil
}
func mysqlPlainFixtureSet(ctx context.Context, config cfg.Config, logger log.Logger) (fixtures.FixtureSet, error) {
mysqlPlainWriter, err := fixtures.NewMysqlPlainFixtureWriter(ctx, config, logger, &fixtures.MysqlPlainMetaData{
TableName: "plain_fixture_example",
Columns: []string{"id", "name"},
})
if err != nil {
return nil, fmt.Errorf("failed to initialize mysql plain writer: %w", err)
}
return fixtures.NewSimpleFixtureSet(fixtures.NamedFixtures[fixtures.MysqlPlainFixtureValues]{
{
Name: "foo2",
Value: fixtures.MysqlPlainFixtureValues{1, "testName1"},
},
{
Name: "foo3",
Value: fixtures.MysqlPlainFixtureValues{2, "testName2"},
},
}, mysqlPlainWriter), nil
}
func dynamodbKvstoreFixtureSet(ctx context.Context, config cfg.Config, logger log.Logger) (fixtures.FixtureSet, error) {
dynamoDbKvStoreWriter, err := fixtures.NewDynamoDbKvStoreFixtureWriter[DynamoDbExampleModel](ctx, config, logger, &mdl.ModelId{
Project: "gosoline",
Environment: "dev",
Family: "example",
Application: "fixture-loader",
Name: "exampleModel",
})
if err != nil {
return nil, fmt.Errorf("failed to initialize dynamodb kvstore writer: %w", err)
}
return fixtures.NewSimpleFixtureSet(fixtures.NamedFixtures[*fixtures.KvStoreFixture]{
{
Name: "kv_somekey",
Value: &fixtures.KvStoreFixture{
Key: "SomeKey",
Value: DynamoDbExampleModel{Name: "Some Name", Value: "Some Value"},
},
},
}, dynamoDbKvStoreWriter), nil
}
func redisFixtureSet(ctx context.Context, config cfg.Config, logger log.Logger) (fixtures.FixtureSet, error) {
redisWriter, err := fixtures.NewRedisFixtureWriter(ctx, config, logger, "default", fixtures.RedisOpSet)
if err != nil {
return nil, fmt.Errorf("failed to initialize redis writer: %w", err)
}
return fixtures.NewSimpleFixtureSet(fixtures.NamedFixtures[*fixtures.RedisFixture]{
{
Name: "redis_example",
Value: &fixtures.RedisFixture{
Key: "example-key",
Value: "bar",
Expiry: 1 * time.Hour,
},
},
}, redisWriter), nil
}
func dynamodbFixtureSet(ctx context.Context, config cfg.Config, logger log.Logger) (fixtures.FixtureSet, error) {
dynamodbWriter, err := fixtures.NewDynamoDbFixtureWriter(ctx, config, logger, &ddb.Settings{
ModelId: mdl.ModelId{
Project: "gosoline",
Environment: "dev",
Family: "example",
Application: "fixture-loader",
Name: "exampleModel",
},
Main: ddb.MainSettings{
Model: DynamoDbExampleModel{},
},
Global: []ddb.GlobalSettings{
{
Name: "IDX_Name",
Model: DynamoDbExampleModel{},
ReadCapacityUnits: 1,
WriteCapacityUnits: 1,
},
},
})
if err != nil {
return nil, fmt.Errorf("failed to initialize dynamodb writer: %w", err)
}
return fixtures.NewSimpleFixtureSet(fixtures.NamedFixtures[*DynamoDbExampleModel]{
{
Name: "ddb",
Value: &DynamoDbExampleModel{Name: "Some Name", Value: "Some Value"},
},
}, dynamodbWriter), nil
}
func blobFixtureSet(ctx context.Context, config cfg.Config, logger log.Logger) (fixtures.FixtureSet, error) {
blobWriter, err := fixtures.NewBlobFixtureWriter(ctx, config, logger, &fixtures.BlobFixturesSettings{
ConfigName: "test",
BasePath: "../../test/test_data/s3_fixtures_test_data",
})
if err != nil {
return nil, fmt.Errorf("failed to initialize blob writer: %w", err)
}
return fixtures.NewSimpleFixtureSet(fixtures.NamedFixtures[*fixtures.BlobFixture]{}, blobWriter), nil
}
func fixtureSetsFactory(ctx context.Context, config cfg.Config, logger log.Logger) ([]fixtures.FixtureSet, error) {
mysqlOrmFs, err := mysqlOrmFixtureSet(ctx, config, logger)
if err != nil {
return nil, err
}
mysqlPlainFs, err := mysqlPlainFixtureSet(ctx, config, logger)
if err != nil {
return nil, err
}
dynamodbKvstoreFs, err := dynamodbKvstoreFixtureSet(ctx, config, logger)
if err != nil {
return nil, err
}
redisFs, err := redisFixtureSet(ctx, config, logger)
if err != nil {
return nil, err
}
dynamodbFs, err := dynamodbFixtureSet(ctx, config, logger)
if err != nil {
return nil, err
}
blobFs, err := blobFixtureSet(ctx, config, logger)
if err != nil {
return nil, err
}
return []fixtures.FixtureSet{
mysqlOrmFs,
mysqlPlainFs,
dynamodbKvstoreFs,
redisFs,
dynamodbFs,
blobFs,
}, nil
}
Named Fixtures
With named fixtures you can create some fixtures and in future fixtures refer to the already created ones, e.g. for referencing (auto numbered) IDs:
type DynamoDbExampleModel struct {
Name string `ddb:"key=hash"`
Value string `ddb:"global=hash"`
}
var namedFixtures = fixtures.NamedFixtures[*DynamoDbExampleModel]{
{
Name: "test",
Value: &DynamoDbExampleModel{Name: "Some Name", Value: "Some Value"},
},
}
func fixtureSetsFactory(ctx context.Context, config cfg.Config, logger log.Logger) ([]fixtures.FixtureSet, error) {
mysqlWriter, err := fixtures.NewMysqlOrmFixtureWriter(ctx, config, logger, &db_repo.Metadata{
ModelId: mdl.ModelId{
Name: "orm_named_fixture_example",
},
})
if err != nil {
return nil, fmt.Errorf("failed to create orm fixture writer: %w", err)
}
return []fixtures.FixtureSet{
fixtures.NewSimpleFixtureSet(namedFixtures, mysqlWriter),
}, nil
}
func main() {
app := application.Default(
application.WithFixtureSetFactory(fixtureSetsFactory),
)
app.Run()
// then you can access them later
fx := namedFixtures.GetValueByName("test")
_ = fx.Value
}
Further Information
- Existing fixtures will be updated instead of created.
- When purge is enabled only the destination of the fixtures will be purged, not everything. That means for example while loading MySQL Fixtures with purge only the tables will be purged not the whole database.
- If you want to use the MySQL ORM based implementation make sure that your fixture struct embeds
db_repo.Model