Unistore Chore: Add OTEL testing harness (#94835)

* add testing harness

* fix mockery and linters

* fix data race in tests

* fix data race in tests

* reduce cardinality of data
This commit is contained in:
Diego Augusto Molina
2024-10-17 08:41:06 -03:00
committed by GitHub
parent 8b9bb2acf6
commit cf08f6762d
14 changed files with 757 additions and 42 deletions
+26 -2
View File
@@ -28,6 +28,30 @@ func (d sqlDB) DriverName() string {
return d.driverName
}
func (d sqlDB) BeginTx(ctx context.Context, opts *sql.TxOptions) (db.Tx, error) {
return d.DB.BeginTx(ctx, opts)
func (d sqlDB) QueryContext(ctx context.Context, query string, args ...any) (db.Rows, error) {
return d.DB.QueryContext(ctx, query, args...)
}
func (d sqlDB) QueryRowContext(ctx context.Context, query string, args ...any) db.Row {
return d.DB.QueryRowContext(ctx, query, args...)
}
func (d sqlDB) BeginTx(ctx context.Context, opts *sql.TxOptions) (db.Tx, error) {
tx, err := d.DB.BeginTx(ctx, opts)
if err != nil {
return nil, err
}
return sqlTx{tx}, err
}
type sqlTx struct {
*sql.Tx
}
func (d sqlTx) QueryContext(ctx context.Context, query string, args ...any) (db.Rows, error) {
return d.Tx.QueryContext(ctx, query, args...)
}
func (d sqlTx) QueryRowContext(ctx context.Context, query string, args ...any) db.Row {
return d.Tx.QueryRowContext(ctx, query, args...)
}
@@ -11,6 +11,7 @@ import (
func TestDB_BeginTx(t *testing.T) {
t.Parallel()
registerTestSQLDrivers()
ctx := testutil.NewDefaultTestContext(t)
sqlDB, err := sql.Open(driverWithIsolationLevelName, "")
+5 -1
View File
@@ -60,6 +60,7 @@ type resourceDBProvider struct {
cfg *setting.Cfg
log log.Logger
migrateFunc func(context.Context, *xorm.Engine, *setting.Cfg) error
tracer trace.Tracer
registerMetrics bool
logQueries bool
}
@@ -77,6 +78,7 @@ func newResourceDBProvider(grafanaDB infraDB.DB, cfg *setting.Cfg, tracer trace.
log: log.New("entity-db"),
logQueries: getter.Bool("log_queries"),
migrateFunc: migrations.MigrateResourceStore,
tracer: tracer,
}
dbType := getter.String("type")
@@ -145,5 +147,7 @@ func (p *resourceDBProvider) init(ctx context.Context) (db.DB, error) {
}
}
return NewDB(p.engine.DB().DB, p.engine.Dialect().DriverName()), nil
d := NewDB(p.engine.DB().DB, p.engine.Dialect().DriverName())
return d, nil
}
@@ -4,6 +4,7 @@ import (
"context"
"database/sql"
"net/http"
"sync"
"testing"
"github.com/google/uuid"
@@ -111,8 +112,18 @@ func newTestInfraDB(t *testing.T, m cfgMap) infraDB.DB {
return sqlstoreDB
}
// globalUnprotectedMutableState controls access to global mutable state found
// in the `setting` package that is not appropriately protected. This would
// ideally be a part of some struct instead of being global, be protected if it
// needs to change, and be unmutable once it no longer needs to change. Example:
// `setting.AppUrl`. Nothing can run in parallel because of this.
// TODO: fix that.
var globalUnprotectedMutableState sync.Mutex
func newCfgFromIniMap(t *testing.T, m cfgMap) *setting.Cfg {
t.Helper()
globalUnprotectedMutableState.Lock()
defer globalUnprotectedMutableState.Unlock()
cfg, err := setting.NewCfgFromINIFile(newTestINIFile(t, m))
require.NoError(t, err)
return cfg
+13 -13
View File
@@ -245,7 +245,7 @@ func (_c *DB_PingContext_Call) RunAndReturn(run func(context.Context) error) *DB
}
// QueryContext provides a mock function with given fields: ctx, query, args
func (_m *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
func (_m *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (db.Rows, error) {
var _ca []interface{}
_ca = append(_ca, ctx, query)
_ca = append(_ca, args...)
@@ -255,16 +255,16 @@ func (_m *DB) QueryContext(ctx context.Context, query string, args ...interface{
panic("no return value specified for QueryContext")
}
var r0 *sql.Rows
var r0 db.Rows
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (*sql.Rows, error)); ok {
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (db.Rows, error)); ok {
return rf(ctx, query, args...)
}
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) *sql.Rows); ok {
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) db.Rows); ok {
r0 = rf(ctx, query, args...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*sql.Rows)
r0 = ret.Get(0).(db.Rows)
}
}
@@ -304,18 +304,18 @@ func (_c *DB_QueryContext_Call) Run(run func(ctx context.Context, query string,
return _c
}
func (_c *DB_QueryContext_Call) Return(_a0 *sql.Rows, _a1 error) *DB_QueryContext_Call {
func (_c *DB_QueryContext_Call) Return(_a0 db.Rows, _a1 error) *DB_QueryContext_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *DB_QueryContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) (*sql.Rows, error)) *DB_QueryContext_Call {
func (_c *DB_QueryContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) (db.Rows, error)) *DB_QueryContext_Call {
_c.Call.Return(run)
return _c
}
// QueryRowContext provides a mock function with given fields: ctx, query, args
func (_m *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
func (_m *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) db.Row {
var _ca []interface{}
_ca = append(_ca, ctx, query)
_ca = append(_ca, args...)
@@ -325,12 +325,12 @@ func (_m *DB) QueryRowContext(ctx context.Context, query string, args ...interfa
panic("no return value specified for QueryRowContext")
}
var r0 *sql.Row
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) *sql.Row); ok {
var r0 db.Row
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) db.Row); ok {
r0 = rf(ctx, query, args...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*sql.Row)
r0 = ret.Get(0).(db.Row)
}
}
@@ -364,12 +364,12 @@ func (_c *DB_QueryRowContext_Call) Run(run func(ctx context.Context, query strin
return _c
}
func (_c *DB_QueryRowContext_Call) Return(_a0 *sql.Row) *DB_QueryRowContext_Call {
func (_c *DB_QueryRowContext_Call) Return(_a0 db.Row) *DB_QueryRowContext_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *DB_QueryRowContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) *sql.Row) *DB_QueryRowContext_Call {
func (_c *DB_QueryRowContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) db.Row) *DB_QueryRowContext_Call {
_c.Call.Return(run)
return _c
}
+132
View File
@@ -0,0 +1,132 @@
// Code generated by mockery v2.43.1. DO NOT EDIT.
package mocks
import mock "github.com/stretchr/testify/mock"
// Row is an autogenerated mock type for the Row type
type Row struct {
mock.Mock
}
type Row_Expecter struct {
mock *mock.Mock
}
func (_m *Row) EXPECT() *Row_Expecter {
return &Row_Expecter{mock: &_m.Mock}
}
// Err provides a mock function with given fields:
func (_m *Row) Err() error {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for Err")
}
var r0 error
if rf, ok := ret.Get(0).(func() error); ok {
r0 = rf()
} else {
r0 = ret.Error(0)
}
return r0
}
// Row_Err_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Err'
type Row_Err_Call struct {
*mock.Call
}
// Err is a helper method to define mock.On call
func (_e *Row_Expecter) Err() *Row_Err_Call {
return &Row_Err_Call{Call: _e.mock.On("Err")}
}
func (_c *Row_Err_Call) Run(run func()) *Row_Err_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *Row_Err_Call) Return(_a0 error) *Row_Err_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *Row_Err_Call) RunAndReturn(run func() error) *Row_Err_Call {
_c.Call.Return(run)
return _c
}
// Scan provides a mock function with given fields: dest
func (_m *Row) Scan(dest ...interface{}) error {
var _ca []interface{}
_ca = append(_ca, dest...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for Scan")
}
var r0 error
if rf, ok := ret.Get(0).(func(...interface{}) error); ok {
r0 = rf(dest...)
} else {
r0 = ret.Error(0)
}
return r0
}
// Row_Scan_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Scan'
type Row_Scan_Call struct {
*mock.Call
}
// Scan is a helper method to define mock.On call
// - dest ...interface{}
func (_e *Row_Expecter) Scan(dest ...interface{}) *Row_Scan_Call {
return &Row_Scan_Call{Call: _e.mock.On("Scan",
append([]interface{}{}, dest...)...)}
}
func (_c *Row_Scan_Call) Run(run func(dest ...interface{})) *Row_Scan_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-0)
for i, a := range args[0:] {
if a != nil {
variadicArgs[i] = a.(interface{})
}
}
run(variadicArgs...)
})
return _c
}
func (_c *Row_Scan_Call) Return(_a0 error) *Row_Scan_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *Row_Scan_Call) RunAndReturn(run func(...interface{}) error) *Row_Scan_Call {
_c.Call.Return(run)
return _c
}
// NewRow creates a new instance of Row. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewRow(t interface {
mock.TestingT
Cleanup(func())
}) *Row {
mock := &Row{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
+267
View File
@@ -0,0 +1,267 @@
// Code generated by mockery v2.43.1. DO NOT EDIT.
package mocks
import mock "github.com/stretchr/testify/mock"
// Rows is an autogenerated mock type for the Rows type
type Rows struct {
mock.Mock
}
type Rows_Expecter struct {
mock *mock.Mock
}
func (_m *Rows) EXPECT() *Rows_Expecter {
return &Rows_Expecter{mock: &_m.Mock}
}
// Close provides a mock function with given fields:
func (_m *Rows) Close() error {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for Close")
}
var r0 error
if rf, ok := ret.Get(0).(func() error); ok {
r0 = rf()
} else {
r0 = ret.Error(0)
}
return r0
}
// Rows_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
type Rows_Close_Call struct {
*mock.Call
}
// Close is a helper method to define mock.On call
func (_e *Rows_Expecter) Close() *Rows_Close_Call {
return &Rows_Close_Call{Call: _e.mock.On("Close")}
}
func (_c *Rows_Close_Call) Run(run func()) *Rows_Close_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *Rows_Close_Call) Return(_a0 error) *Rows_Close_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *Rows_Close_Call) RunAndReturn(run func() error) *Rows_Close_Call {
_c.Call.Return(run)
return _c
}
// Err provides a mock function with given fields:
func (_m *Rows) Err() error {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for Err")
}
var r0 error
if rf, ok := ret.Get(0).(func() error); ok {
r0 = rf()
} else {
r0 = ret.Error(0)
}
return r0
}
// Rows_Err_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Err'
type Rows_Err_Call struct {
*mock.Call
}
// Err is a helper method to define mock.On call
func (_e *Rows_Expecter) Err() *Rows_Err_Call {
return &Rows_Err_Call{Call: _e.mock.On("Err")}
}
func (_c *Rows_Err_Call) Run(run func()) *Rows_Err_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *Rows_Err_Call) Return(_a0 error) *Rows_Err_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *Rows_Err_Call) RunAndReturn(run func() error) *Rows_Err_Call {
_c.Call.Return(run)
return _c
}
// Next provides a mock function with given fields:
func (_m *Rows) Next() bool {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for Next")
}
var r0 bool
if rf, ok := ret.Get(0).(func() bool); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// Rows_Next_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Next'
type Rows_Next_Call struct {
*mock.Call
}
// Next is a helper method to define mock.On call
func (_e *Rows_Expecter) Next() *Rows_Next_Call {
return &Rows_Next_Call{Call: _e.mock.On("Next")}
}
func (_c *Rows_Next_Call) Run(run func()) *Rows_Next_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *Rows_Next_Call) Return(_a0 bool) *Rows_Next_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *Rows_Next_Call) RunAndReturn(run func() bool) *Rows_Next_Call {
_c.Call.Return(run)
return _c
}
// NextResultSet provides a mock function with given fields:
func (_m *Rows) NextResultSet() bool {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for NextResultSet")
}
var r0 bool
if rf, ok := ret.Get(0).(func() bool); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// Rows_NextResultSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NextResultSet'
type Rows_NextResultSet_Call struct {
*mock.Call
}
// NextResultSet is a helper method to define mock.On call
func (_e *Rows_Expecter) NextResultSet() *Rows_NextResultSet_Call {
return &Rows_NextResultSet_Call{Call: _e.mock.On("NextResultSet")}
}
func (_c *Rows_NextResultSet_Call) Run(run func()) *Rows_NextResultSet_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *Rows_NextResultSet_Call) Return(_a0 bool) *Rows_NextResultSet_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *Rows_NextResultSet_Call) RunAndReturn(run func() bool) *Rows_NextResultSet_Call {
_c.Call.Return(run)
return _c
}
// Scan provides a mock function with given fields: dest
func (_m *Rows) Scan(dest ...interface{}) error {
var _ca []interface{}
_ca = append(_ca, dest...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for Scan")
}
var r0 error
if rf, ok := ret.Get(0).(func(...interface{}) error); ok {
r0 = rf(dest...)
} else {
r0 = ret.Error(0)
}
return r0
}
// Rows_Scan_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Scan'
type Rows_Scan_Call struct {
*mock.Call
}
// Scan is a helper method to define mock.On call
// - dest ...interface{}
func (_e *Rows_Expecter) Scan(dest ...interface{}) *Rows_Scan_Call {
return &Rows_Scan_Call{Call: _e.mock.On("Scan",
append([]interface{}{}, dest...)...)}
}
func (_c *Rows_Scan_Call) Run(run func(dest ...interface{})) *Rows_Scan_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-0)
for i, a := range args[0:] {
if a != nil {
variadicArgs[i] = a.(interface{})
}
}
run(variadicArgs...)
})
return _c
}
func (_c *Rows_Scan_Call) Return(_a0 error) *Rows_Scan_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *Rows_Scan_Call) RunAndReturn(run func(...interface{}) error) *Rows_Scan_Call {
_c.Call.Return(run)
return _c
}
// NewRows creates a new instance of Rows. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewRows(t interface {
mock.TestingT
Cleanup(func())
}) *Rows {
mock := &Rows{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
+14 -13
View File
@@ -5,6 +5,7 @@ package mocks
import (
context "context"
db "github.com/grafana/grafana/pkg/storage/unified/sql/db"
mock "github.com/stretchr/testify/mock"
sql "database/sql"
@@ -139,7 +140,7 @@ func (_c *Tx_ExecContext_Call) RunAndReturn(run func(context.Context, string, ..
}
// QueryContext provides a mock function with given fields: ctx, query, args
func (_m *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
func (_m *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (db.Rows, error) {
var _ca []interface{}
_ca = append(_ca, ctx, query)
_ca = append(_ca, args...)
@@ -149,16 +150,16 @@ func (_m *Tx) QueryContext(ctx context.Context, query string, args ...interface{
panic("no return value specified for QueryContext")
}
var r0 *sql.Rows
var r0 db.Rows
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (*sql.Rows, error)); ok {
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (db.Rows, error)); ok {
return rf(ctx, query, args...)
}
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) *sql.Rows); ok {
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) db.Rows); ok {
r0 = rf(ctx, query, args...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*sql.Rows)
r0 = ret.Get(0).(db.Rows)
}
}
@@ -198,18 +199,18 @@ func (_c *Tx_QueryContext_Call) Run(run func(ctx context.Context, query string,
return _c
}
func (_c *Tx_QueryContext_Call) Return(_a0 *sql.Rows, _a1 error) *Tx_QueryContext_Call {
func (_c *Tx_QueryContext_Call) Return(_a0 db.Rows, _a1 error) *Tx_QueryContext_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *Tx_QueryContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) (*sql.Rows, error)) *Tx_QueryContext_Call {
func (_c *Tx_QueryContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) (db.Rows, error)) *Tx_QueryContext_Call {
_c.Call.Return(run)
return _c
}
// QueryRowContext provides a mock function with given fields: ctx, query, args
func (_m *Tx) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
func (_m *Tx) QueryRowContext(ctx context.Context, query string, args ...interface{}) db.Row {
var _ca []interface{}
_ca = append(_ca, ctx, query)
_ca = append(_ca, args...)
@@ -219,12 +220,12 @@ func (_m *Tx) QueryRowContext(ctx context.Context, query string, args ...interfa
panic("no return value specified for QueryRowContext")
}
var r0 *sql.Row
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) *sql.Row); ok {
var r0 db.Row
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) db.Row); ok {
r0 = rf(ctx, query, args...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*sql.Row)
r0 = ret.Get(0).(db.Row)
}
}
@@ -258,12 +259,12 @@ func (_c *Tx_QueryRowContext_Call) Run(run func(ctx context.Context, query strin
return _c
}
func (_c *Tx_QueryRowContext_Call) Return(_a0 *sql.Row) *Tx_QueryRowContext_Call {
func (_c *Tx_QueryRowContext_Call) Return(_a0 db.Row) *Tx_QueryRowContext_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *Tx_QueryRowContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) *sql.Row) *Tx_QueryRowContext_Call {
func (_c *Tx_QueryRowContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) db.Row) *Tx_QueryRowContext_Call {
_c.Call.Return(run)
return _c
}
+142
View File
@@ -0,0 +1,142 @@
// Code generated by mockery v2.43.1. DO NOT EDIT.
package mocks
import mock "github.com/stretchr/testify/mock"
// Result is an autogenerated mock type for the result type
type Result struct {
mock.Mock
}
type Result_Expecter struct {
mock *mock.Mock
}
func (_m *Result) EXPECT() *Result_Expecter {
return &Result_Expecter{mock: &_m.Mock}
}
// LastInsertId provides a mock function with given fields:
func (_m *Result) LastInsertId() (int64, error) {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for LastInsertId")
}
var r0 int64
var r1 error
if rf, ok := ret.Get(0).(func() (int64, error)); ok {
return rf()
}
if rf, ok := ret.Get(0).(func() int64); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(int64)
}
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Result_LastInsertId_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LastInsertId'
type Result_LastInsertId_Call struct {
*mock.Call
}
// LastInsertId is a helper method to define mock.On call
func (_e *Result_Expecter) LastInsertId() *Result_LastInsertId_Call {
return &Result_LastInsertId_Call{Call: _e.mock.On("LastInsertId")}
}
func (_c *Result_LastInsertId_Call) Run(run func()) *Result_LastInsertId_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *Result_LastInsertId_Call) Return(_a0 int64, _a1 error) *Result_LastInsertId_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *Result_LastInsertId_Call) RunAndReturn(run func() (int64, error)) *Result_LastInsertId_Call {
_c.Call.Return(run)
return _c
}
// RowsAffected provides a mock function with given fields:
func (_m *Result) RowsAffected() (int64, error) {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for RowsAffected")
}
var r0 int64
var r1 error
if rf, ok := ret.Get(0).(func() (int64, error)); ok {
return rf()
}
if rf, ok := ret.Get(0).(func() int64); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(int64)
}
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Result_RowsAffected_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RowsAffected'
type Result_RowsAffected_Call struct {
*mock.Call
}
// RowsAffected is a helper method to define mock.On call
func (_e *Result_Expecter) RowsAffected() *Result_RowsAffected_Call {
return &Result_RowsAffected_Call{Call: _e.mock.On("RowsAffected")}
}
func (_c *Result_RowsAffected_Call) Run(run func()) *Result_RowsAffected_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *Result_RowsAffected_Call) Return(_a0 int64, _a1 error) *Result_RowsAffected_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *Result_RowsAffected_Call) RunAndReturn(run func() (int64, error)) *Result_RowsAffected_Call {
_c.Call.Return(run)
return _c
}
// NewResult creates a new instance of Result. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewResult(t interface {
mock.TestingT
Cleanup(func())
}) *Result {
mock := &Result{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
+56
View File
@@ -0,0 +1,56 @@
package mocks
import (
"reflect"
"testing"
mock "github.com/stretchr/testify/mock"
)
func NewRowWithValues(t *testing.T, values ...any) *Row {
row := NewRow(t)
row.EXPECT().Err().Return(nil).Once() // should check error
ExpectRowValues(t, row, values...)
return row
}
func ExpectRowValues(t *testing.T, row *Row, values ...any) *Row_Scan_Call {
return row.EXPECT().Scan(mock.Anything).RunAndReturn(func(dsts ...any) error {
scan(t, dsts, values)
return nil
})
}
func scan(t *testing.T, dsts, srcs []any) {
t.Helper()
if len(dsts) > len(srcs) {
t.Fatalf("%d destination values, but only %d source values", len(dsts),
len(srcs))
return
}
for i := range dsts {
src := reflect.ValueOf(srcs[i])
if !src.IsValid() {
t.Fatalf("%d-eth value to be returned by the mocked db is"+
" invalid: %#v", i, srcs[i])
return
}
dst := reflect.ValueOf(dsts[i])
if !dst.IsValid() || dst.Kind() != reflect.Pointer {
t.Fatalf("%d-eth argument passed to Scan is invalid or not"+
" a pointer: %#v", i, dsts[i])
return
}
dst = dst.Elem() // get element to which the pointer points to
if !dst.CanSet() || !src.Type().AssignableTo(dst.Type()) {
t.Fatalf("%d-eth destination cannot be set, orcannot be assigned "+
"the value; type of destination: %T; value that would be "+
"assigned: %#v", i, dsts[i], srcs[i])
return
}
dst.Set(src)
}
}
+31 -3
View File
@@ -8,6 +8,9 @@ import (
//go:generate mockery --with-expecter --name DB
//go:generate mockery --with-expecter --name Tx
//go:generate mockery --with-expecter --name Row
//go:generate mockery --with-expecter --name Rows
//go:generate mockery --with-expecter --exported --name result
const (
DriverPostgres = "postgres"
@@ -59,9 +62,34 @@ type Tx interface {
// ContextExecer is a set of database operation methods that take
// context.Context.
type ContextExecer interface {
ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
ExecContext(ctx context.Context, query string, args ...any) (Result, error)
QueryContext(ctx context.Context, query string, args ...any) (Rows, error)
QueryRowContext(ctx context.Context, query string, args ...any) Row
}
// Row is the set of methods from *sql.Row that we use.
type Row interface {
Err() error
Scan(dest ...any) error
}
// Rows is the set of methods from *sql.Rows that we use.
type Rows interface {
Close() error
Err() error
Next() bool
NextResultSet() bool
Scan(dest ...any) error
}
// Result is the standard sql.Result interface, for convenience.
type Result = sql.Result
// result is needed for mockery, since it doesn't support type aliases.
//
//nolint:unused
type result interface {
Result
}
// WithTxFunc is an adapter to be able to provide the DB.WithTx method as an