mirror of https://github.com/VinGarcia/ksql.git
Add more tests to ksql.Query()
parent
74cb87bea0
commit
4b37adc905
|
@ -93,11 +93,11 @@ func GetTagInfo(key reflect.Type) (StructInfo, error) {
|
|||
|
||||
func getCachedTagInfo(tagInfoCache *sync.Map, key reflect.Type) (StructInfo, error) {
|
||||
if data, found := tagInfoCache.Load(key); found {
|
||||
if info, ok := data.(StructInfo); !ok {
|
||||
info, ok := data.(StructInfo)
|
||||
if !ok {
|
||||
return StructInfo{}, fmt.Errorf("invalid cache entry, expected type StructInfo, found %T", data)
|
||||
} else {
|
||||
return info, nil
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
info, err := getTagNames(key)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package ksql
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// mockTxBeginner mocks the ksql.TxBeginner interface
|
||||
type mockTxBeginner struct {
|
||||
|
@ -26,6 +28,40 @@ func (m mockDBAdapter) QueryContext(ctx context.Context, query string, args ...i
|
|||
return m.QueryContextFn(ctx, query, args...)
|
||||
}
|
||||
|
||||
type mockRows struct {
|
||||
ScanFn func(...interface{}) error
|
||||
CloseFn func() error
|
||||
NextFn func() bool
|
||||
ErrFn func() error
|
||||
ColumnsFn func() ([]string, error)
|
||||
}
|
||||
|
||||
func (m mockRows) Scan(values ...interface{}) error {
|
||||
return m.ScanFn(values...)
|
||||
}
|
||||
|
||||
func (m mockRows) Close() error {
|
||||
if m.CloseFn == nil {
|
||||
return nil
|
||||
}
|
||||
return m.CloseFn()
|
||||
}
|
||||
|
||||
func (m mockRows) Next() bool {
|
||||
return m.NextFn()
|
||||
}
|
||||
|
||||
func (m mockRows) Err() error {
|
||||
if m.ErrFn == nil {
|
||||
return nil
|
||||
}
|
||||
return m.ErrFn()
|
||||
}
|
||||
|
||||
func (m mockRows) Columns() ([]string, error) {
|
||||
return m.ColumnsFn()
|
||||
}
|
||||
|
||||
// mockTx mocks the ksql.Tx interface
|
||||
type mockTx struct {
|
||||
DBAdapter
|
||||
|
|
|
@ -403,6 +403,23 @@ func QueryTest(
|
|||
tt.AssertErrContains(t, err, "error running query")
|
||||
})
|
||||
|
||||
t.Run("should report error if the TagInfoCache returns an error", func(t *testing.T) {
|
||||
db, closer := newDBAdapter(t)
|
||||
defer closer.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
c := newTestDB(db, driver)
|
||||
|
||||
// Provoque an error by sending an invalid struct:
|
||||
var users []struct {
|
||||
ID int `ksql:"id"`
|
||||
// Private names cannot have ksql tags:
|
||||
badPrivateField string `ksql:"name"`
|
||||
}
|
||||
err := c.Query(ctx, &users, `SELECT * FROM users`)
|
||||
tt.AssertErrContains(t, err, "badPrivateField")
|
||||
})
|
||||
|
||||
t.Run("should report error if using nested struct and the query starts with SELECT", func(t *testing.T) {
|
||||
db, closer := newDBAdapter(t)
|
||||
defer closer.Close()
|
||||
|
@ -471,6 +488,81 @@ func QueryTest(
|
|||
err := c.Query(ctx, &rows, `FROM users u JOIN posts p ON u.id = p.user_id`)
|
||||
tt.AssertErrContains(t, err, "same ksql tag name", "invalid_repeated_name")
|
||||
})
|
||||
|
||||
t.Run("should report error if DBAdapter.Scan() returns an error", func(t *testing.T) {
|
||||
db := mockDBAdapter{
|
||||
QueryContextFn: func(ctx context.Context, query string, args ...interface{}) (Rows, error) {
|
||||
return mockRows{
|
||||
ColumnsFn: func() ([]string, error) {
|
||||
return []string{"id", "name", "age", "address"}, nil
|
||||
},
|
||||
NextFn: func() bool { return true },
|
||||
ScanFn: func(values ...interface{}) error {
|
||||
return errors.New("fakeScanErr")
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
c := newTestDB(db, driver)
|
||||
|
||||
var users []user
|
||||
err := c.Query(ctx, &users, `SELECT * FROM users`)
|
||||
tt.AssertErrContains(t, err, "fakeScanErr")
|
||||
})
|
||||
|
||||
t.Run("should report error if DBAdapter.Err() returns an error", func(t *testing.T) {
|
||||
db := mockDBAdapter{
|
||||
QueryContextFn: func(ctx context.Context, query string, args ...interface{}) (Rows, error) {
|
||||
return mockRows{
|
||||
ColumnsFn: func() ([]string, error) {
|
||||
return []string{"id", "name", "age", "address"}, nil
|
||||
},
|
||||
NextFn: func() bool { return false },
|
||||
ScanFn: func(values ...interface{}) error {
|
||||
return nil
|
||||
},
|
||||
ErrFn: func() error {
|
||||
return errors.New("fakeErrMsg")
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
c := newTestDB(db, driver)
|
||||
|
||||
var users []user
|
||||
err := c.Query(ctx, &users, `SELECT * FROM users`)
|
||||
tt.AssertErrContains(t, err, "fakeErrMsg")
|
||||
})
|
||||
|
||||
t.Run("should report error if DBAdapter.Close() returns an error", func(t *testing.T) {
|
||||
db := mockDBAdapter{
|
||||
QueryContextFn: func(ctx context.Context, query string, args ...interface{}) (Rows, error) {
|
||||
return mockRows{
|
||||
ColumnsFn: func() ([]string, error) {
|
||||
return []string{"id", "name", "age", "address"}, nil
|
||||
},
|
||||
NextFn: func() bool { return false },
|
||||
ScanFn: func(values ...interface{}) error {
|
||||
return nil
|
||||
},
|
||||
CloseFn: func() error {
|
||||
return errors.New("fakeCloseErr")
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
c := newTestDB(db, driver)
|
||||
|
||||
var users []user
|
||||
err := c.Query(ctx, &users, `SELECT * FROM users`)
|
||||
tt.AssertErrContains(t, err, "fakeCloseErr")
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue