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
    },
}