Packages
mock
Function-override test doubles for every contract interface. No mock generation frameworks needed — override only the methods your test uses.
mock.Database
import "github.com/BounkhongDev/bkgo/mock"
db := &mock.Database{
QueryRowFn: func(ctx context.Context, sql string, args ...any) contract.Row {
return mock.NewRow("user-123", "Bounkhong", "bk@example.com")
},
ExecFn: func(ctx context.Context, sql string, args ...any) error {
return nil
},
}
// Unset fields (QueryFn, PingFn, CloseFn) panic if called —
// so your test fails loudly if unexpected methods are triggered.mock.Row helpers
// Successful row — Scan populates fields via reflect
row := mock.NewRow("user-123", "Bounkhong", "bk@example.com")
// Error row — Scan returns the error
row := mock.NewRowError(pgx.ErrNoRows)
row := mock.NewRowError(errors.New("db timeout"))mock.Rows helpers
// Multiple rows
rows := mock.NewRows([][]any{
{"user-1", "Alice"},
{"user-2", "Bob"},
})
// Error rows — Next() returns false, Err() returns the error
rows := mock.NewRowsError(errors.New("scan failed"))mock.Cache
In-memory cache using a map[string][]byte with sync.RWMutex. Values are serialized with json.Marshal — identical to the real Redis adapter.
cache := mock.NewCache()
cache.Set(ctx, "user:123", user, time.Minute)
cache.Get(ctx, "user:123", &dest)
cache.Delete(ctx, "user:123")
// Reset between tests
cache.Flush()mock.TransactionalDB
txDB := &mock.TransactionalDB{
Database: mock.Database{
ExecFn: func(ctx context.Context, sql string, args ...any) error {
return nil
},
},
BeginTxFn: func(ctx context.Context) (contract.Tx, error) {
return &mock.Tx{
ExecFn: func(ctx context.Context, sql string, args ...any) error {
return nil
},
CommitFn: func(ctx context.Context) error { return nil },
RollbackFn: func(ctx context.Context) error { return nil },
}, nil
},
}