mirror of https://github.com/VinGarcia/ksql.git
Deprecate kstructs in favor of ksqltest
parent
9b18a8fbcf
commit
06b871a418
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/ditointernet/go-assert"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
"github.com/vingarcia/ksql"
|
||||
"github.com/vingarcia/ksql/kstructs"
|
||||
"github.com/vingarcia/ksql/ksqltest"
|
||||
"github.com/vingarcia/ksql/nullable"
|
||||
)
|
||||
|
||||
|
@ -58,7 +58,7 @@ func TestCreateUser(t *testing.T) {
|
|||
//
|
||||
// If you are inserting an anonymous struct (not usual) this function
|
||||
// can make your tests shorter:
|
||||
uMap, err := kstructs.StructToMap(record)
|
||||
uMap, err := ksqltest.StructToMap(record)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ func TestUpdateUserScore(t *testing.T) {
|
|||
DoAndReturn(func(ctx context.Context, result interface{}, query string, params ...interface{}) error {
|
||||
// This function will use reflection to fill the
|
||||
// struct fields with the values from the map
|
||||
return kstructs.FillStructWith(result, map[string]interface{}{
|
||||
return ksqltest.FillStructWith(result, map[string]interface{}{
|
||||
// Use int this map the keys you set on the ksql tags, e.g. `ksql:"score"`
|
||||
// Each of these fields represent the database rows returned
|
||||
// by the query.
|
||||
|
@ -138,7 +138,7 @@ func TestListUsers(t *testing.T) {
|
|||
DoAndReturn(func(ctx context.Context, result interface{}, query string, params ...interface{}) error {
|
||||
// This function will use reflection to fill the
|
||||
// struct fields with the values from the map
|
||||
return kstructs.FillStructWith(result, map[string]interface{}{
|
||||
return ksqltest.FillStructWith(result, map[string]interface{}{
|
||||
// Use int this map the keys you set on the ksql tags, e.g. `ksql:"score"`
|
||||
// Each of these fields represent the database rows returned
|
||||
// by the query.
|
||||
|
@ -147,7 +147,7 @@ func TestListUsers(t *testing.T) {
|
|||
}),
|
||||
mockDB.EXPECT().Query(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
|
||||
DoAndReturn(func(ctx context.Context, results interface{}, query string, params ...interface{}) error {
|
||||
return kstructs.FillSliceWith(results, []map[string]interface{}{
|
||||
return ksqltest.FillSliceWith(results, []map[string]interface{}{
|
||||
{
|
||||
"id": 1,
|
||||
"name": "fake name",
|
||||
|
@ -198,7 +198,7 @@ func TestStreamAllUsers(t *testing.T) {
|
|||
mockDB.EXPECT().QueryChunks(gomock.Any(), gomock.Any()).
|
||||
DoAndReturn(func(ctx context.Context, parser ksql.ChunkParser) error {
|
||||
// Chunk 1:
|
||||
err := kstructs.CallFunctionWithRows(parser.ForEachChunk, []map[string]interface{}{
|
||||
err := ksqltest.CallFunctionWithRows(parser.ForEachChunk, []map[string]interface{}{
|
||||
{
|
||||
"id": 1,
|
||||
"name": "fake name",
|
||||
|
@ -215,7 +215,7 @@ func TestStreamAllUsers(t *testing.T) {
|
|||
}
|
||||
|
||||
// Chunk 2:
|
||||
err = kstructs.CallFunctionWithRows(parser.ForEachChunk, []map[string]interface{}{
|
||||
err = ksqltest.CallFunctionWithRows(parser.ForEachChunk, []map[string]interface{}{
|
||||
{
|
||||
"id": 3,
|
||||
"name": "yet another fake name",
|
||||
|
|
10
ksql.go
10
ksql.go
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vingarcia/ksql/internal/structs"
|
||||
"github.com/vingarcia/ksql/kstructs"
|
||||
"github.com/vingarcia/ksql/ksqltest"
|
||||
)
|
||||
|
||||
var selectQueryCache = map[string]map[reflect.Type]string{}
|
||||
|
@ -593,7 +593,7 @@ func normalizeIDsAsMap(idNames []string, idOrMap interface{}) (idMap map[string]
|
|||
|
||||
switch t.Kind() {
|
||||
case reflect.Struct:
|
||||
idMap, err = kstructs.StructToMap(idOrMap)
|
||||
idMap, err = ksqltest.StructToMap(idOrMap)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get ID(s) from input record")
|
||||
}
|
||||
|
@ -691,7 +691,7 @@ func buildInsertQuery(
|
|||
info structs.StructInfo,
|
||||
record interface{},
|
||||
) (query string, params []interface{}, scanValues []interface{}, err error) {
|
||||
recordMap, err := kstructs.StructToMap(record)
|
||||
recordMap, err := ksqltest.StructToMap(record)
|
||||
if err != nil {
|
||||
return "", nil, nil, err
|
||||
}
|
||||
|
@ -785,7 +785,7 @@ func buildUpdateQuery(
|
|||
record interface{},
|
||||
idFieldNames ...string,
|
||||
) (query string, args []interface{}, err error) {
|
||||
recordMap, err := kstructs.StructToMap(record)
|
||||
recordMap, err := ksqltest.StructToMap(record)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
@ -927,7 +927,7 @@ func scanRowsFromType(
|
|||
if info.IsNestedStruct {
|
||||
// This version is positional meaning that it expect the arguments
|
||||
// to follow an specific order. It's ok because we don't allow the
|
||||
// user to type the "SELECT" part of the query for nested kstructs.
|
||||
// user to type the "SELECT" part of the query for nested ksqltest.
|
||||
scanArgs, err = getScanArgsForNestedStructs(dialect, rows, t, v, info)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
package ksqltest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/vingarcia/ksql/internal/structs"
|
||||
)
|
||||
|
||||
// StructToMap converts any struct type to a map based on
|
||||
// the tag named `ksql`, i.e. `ksql:"map_key_name"`
|
||||
//
|
||||
// Valid pointers are dereferenced and copied to the map,
|
||||
// null pointers are ignored.
|
||||
//
|
||||
// This function is efficient in the fact that it caches
|
||||
// the slower steps of the reflection required to perform
|
||||
// this task.
|
||||
func StructToMap(obj interface{}) (map[string]interface{}, error) {
|
||||
return structs.StructToMap(obj)
|
||||
}
|
||||
|
||||
// FillStructWith is meant to be used on unit tests to mock
|
||||
// the response from the database.
|
||||
//
|
||||
// The first argument is any struct you are passing to a ksql func,
|
||||
// and the second is a map representing a database row you want
|
||||
// to use to update this struct.
|
||||
func FillStructWith(record interface{}, dbRow map[string]interface{}) error {
|
||||
v := reflect.ValueOf(record)
|
||||
t := v.Type()
|
||||
|
||||
if t.Kind() != reflect.Ptr {
|
||||
return fmt.Errorf(
|
||||
"FillStructWith: expected input to be a pointer to struct but got %T",
|
||||
record,
|
||||
)
|
||||
}
|
||||
|
||||
t = t.Elem()
|
||||
v = v.Elem()
|
||||
|
||||
if t.Kind() != reflect.Struct {
|
||||
return fmt.Errorf(
|
||||
"FillStructWith: expected input to be a pointer to a struct, but got %T",
|
||||
record,
|
||||
)
|
||||
}
|
||||
|
||||
info, err := structs.GetTagInfo(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for colName, rawSrc := range dbRow {
|
||||
fieldInfo := info.ByName(colName)
|
||||
if !fieldInfo.Valid {
|
||||
// Ignore columns not tagged with `ksql:"..."`
|
||||
continue
|
||||
}
|
||||
|
||||
src := structs.NewPtrConverter(rawSrc)
|
||||
dest := v.Field(fieldInfo.Index)
|
||||
destType := t.Field(fieldInfo.Index).Type
|
||||
|
||||
destValue, err := src.Convert(destType)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("FillStructWith: error on field `%s`", colName))
|
||||
}
|
||||
|
||||
dest.Set(destValue)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FillSliceWith is meant to be used on unit tests to mock
|
||||
// the response from the database.
|
||||
//
|
||||
// The first argument is any slice of structs you are passing to a ksql func,
|
||||
// and the second is a slice of maps representing the database rows you want
|
||||
// to use to update this struct.
|
||||
func FillSliceWith(entities interface{}, dbRows []map[string]interface{}) error {
|
||||
sliceRef := reflect.ValueOf(entities)
|
||||
sliceType := sliceRef.Type()
|
||||
if sliceType.Kind() != reflect.Ptr {
|
||||
return fmt.Errorf(
|
||||
"FillSliceWith: expected input to be a pointer to a slice of structs but got %v",
|
||||
sliceType,
|
||||
)
|
||||
}
|
||||
|
||||
structType, isSliceOfPtrs, err := structs.DecodeAsSliceOfStructs(sliceType.Elem())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "FillSliceWith")
|
||||
}
|
||||
|
||||
slice := sliceRef.Elem()
|
||||
for idx, row := range dbRows {
|
||||
if slice.Len() <= idx {
|
||||
var elemValue reflect.Value
|
||||
elemValue = reflect.New(structType)
|
||||
if !isSliceOfPtrs {
|
||||
elemValue = elemValue.Elem()
|
||||
}
|
||||
slice = reflect.Append(slice, elemValue)
|
||||
}
|
||||
|
||||
err := FillStructWith(slice.Index(idx).Addr().Interface(), row)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "FillSliceWith")
|
||||
}
|
||||
}
|
||||
|
||||
sliceRef.Elem().Set(slice)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CallFunctionWithRows was created for helping test the QueryChunks method
|
||||
func CallFunctionWithRows(fn interface{}, rows []map[string]interface{}) error {
|
||||
fnValue := reflect.ValueOf(fn)
|
||||
chunkType, err := structs.ParseInputFunc(fn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
chunk := reflect.MakeSlice(chunkType, 0, len(rows))
|
||||
|
||||
// Create a pointer to a slice (required by FillSliceWith)
|
||||
chunkPtr := reflect.New(chunkType)
|
||||
chunkPtr.Elem().Set(chunk)
|
||||
|
||||
err = FillSliceWith(chunkPtr.Interface(), rows)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err, _ = fnValue.Call([]reflect.Value{chunkPtr.Elem()})[0].Interface().(error)
|
||||
|
||||
return err
|
||||
}
|
|
@ -0,0 +1,395 @@
|
|||
package ksqltest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/ditointernet/go-assert"
|
||||
tt "github.com/vingarcia/ksql/internal/testtools"
|
||||
"github.com/vingarcia/ksql/nullable"
|
||||
)
|
||||
|
||||
func TestStructToMap(t *testing.T) {
|
||||
type S1 struct {
|
||||
Name string `ksql:"name_attr"`
|
||||
Age int `ksql:"age_attr"`
|
||||
}
|
||||
t.Run("should convert plain structs to maps", func(t *testing.T) {
|
||||
m, err := StructToMap(S1{
|
||||
Name: "my name",
|
||||
Age: 22,
|
||||
})
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, map[string]interface{}{
|
||||
"name_attr": "my name",
|
||||
"age_attr": 22,
|
||||
}, m)
|
||||
})
|
||||
|
||||
t.Run("should not ignore zero value attrs, if they are not pointers", func(t *testing.T) {
|
||||
m, err := StructToMap(S1{
|
||||
Name: "",
|
||||
Age: 0,
|
||||
})
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, map[string]interface{}{
|
||||
"name_attr": "",
|
||||
"age_attr": 0,
|
||||
}, m)
|
||||
})
|
||||
|
||||
type S2 struct {
|
||||
Name *string `ksql:"name"`
|
||||
Age *int `ksql:"age"`
|
||||
}
|
||||
|
||||
t.Run("should not ignore not nil pointers", func(t *testing.T) {
|
||||
str := ""
|
||||
age := 0
|
||||
m, err := StructToMap(S2{
|
||||
Name: &str,
|
||||
Age: &age,
|
||||
})
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, map[string]interface{}{
|
||||
"name": "",
|
||||
"age": 0,
|
||||
}, m)
|
||||
})
|
||||
|
||||
t.Run("should ignore nil pointers", func(t *testing.T) {
|
||||
m, err := StructToMap(S2{
|
||||
Name: nil,
|
||||
Age: nil,
|
||||
})
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, map[string]interface{}{}, m)
|
||||
})
|
||||
|
||||
t.Run("should ignore fields not tagged with ksql", func(t *testing.T) {
|
||||
m, err := StructToMap(struct {
|
||||
Name string `ksql:"name_attr"`
|
||||
Age int `ksql:"age_attr"`
|
||||
NotPartOfTheQuery int
|
||||
}{
|
||||
Name: "fake-name",
|
||||
Age: 42,
|
||||
NotPartOfTheQuery: 42,
|
||||
})
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, map[string]interface{}{
|
||||
"name_attr": "fake-name",
|
||||
"age_attr": 42,
|
||||
}, m)
|
||||
})
|
||||
|
||||
t.Run("should return error for duplicated ksql tag names", func(t *testing.T) {
|
||||
_, err := StructToMap(struct {
|
||||
Name string `ksql:"name_attr"`
|
||||
DuplicatedName string `ksql:"name_attr"`
|
||||
Age int `ksql:"age_attr"`
|
||||
}{
|
||||
Name: "fake-name",
|
||||
Age: 42,
|
||||
DuplicatedName: "fake-duplicated-name",
|
||||
})
|
||||
|
||||
assert.NotEqual(t, nil, err)
|
||||
})
|
||||
|
||||
t.Run("should return error for structs with no ksql tags", func(t *testing.T) {
|
||||
_, err := StructToMap(struct {
|
||||
Name string
|
||||
Age int `json:"age"`
|
||||
}{
|
||||
Name: "fake-name",
|
||||
Age: 42,
|
||||
})
|
||||
|
||||
assert.NotEqual(t, nil, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFillStructWith(t *testing.T) {
|
||||
t.Run("should fill a struct correctly", func(t *testing.T) {
|
||||
var user struct {
|
||||
Name string `ksql:"name"`
|
||||
Age int `ksql:"age"`
|
||||
}
|
||||
err := FillStructWith(&user, map[string]interface{}{
|
||||
"name": "Breno",
|
||||
"age": 22,
|
||||
})
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, "Breno", user.Name)
|
||||
assert.Equal(t, 22, user.Age)
|
||||
})
|
||||
|
||||
t.Run("should fill ptr fields with ptr values", func(t *testing.T) {
|
||||
var user struct {
|
||||
Name *string `ksql:"name"`
|
||||
Age *int `ksql:"age"`
|
||||
}
|
||||
err := FillStructWith(&user, map[string]interface{}{
|
||||
"name": nullable.String("Breno"),
|
||||
"age": nullable.Int(22),
|
||||
})
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, nullable.String("Breno"), user.Name)
|
||||
assert.Equal(t, nullable.Int(22), user.Age)
|
||||
})
|
||||
|
||||
t.Run("should fill ptr fields with non-ptr values", func(t *testing.T) {
|
||||
var user struct {
|
||||
Name *string `ksql:"name"`
|
||||
Age *int `ksql:"age"`
|
||||
}
|
||||
err := FillStructWith(&user, map[string]interface{}{
|
||||
"name": "Breno",
|
||||
"age": 22,
|
||||
})
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, nullable.String("Breno"), user.Name)
|
||||
assert.Equal(t, nullable.Int(22), user.Age)
|
||||
})
|
||||
|
||||
t.Run("should fill non ptr fields with ptr values", func(t *testing.T) {
|
||||
var user struct {
|
||||
Name string `ksql:"name"`
|
||||
Age int `ksql:"age"`
|
||||
}
|
||||
err := FillStructWith(&user, map[string]interface{}{
|
||||
"name": nullable.String("Breno"),
|
||||
"age": nullable.Int(22),
|
||||
})
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, "Breno", user.Name)
|
||||
assert.Equal(t, 22, user.Age)
|
||||
})
|
||||
|
||||
t.Run("should fill ptr fields with nil when necessary", func(t *testing.T) {
|
||||
var user struct {
|
||||
Name *string `ksql:"name"`
|
||||
Age *int `ksql:"age"`
|
||||
}
|
||||
err := FillStructWith(&user, map[string]interface{}{
|
||||
"name": nil,
|
||||
"age": nil,
|
||||
})
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, (*string)(nil), user.Name)
|
||||
assert.Equal(t, (*int)(nil), user.Age)
|
||||
})
|
||||
|
||||
t.Run("should interpret nil fields as zero values when necessary", func(t *testing.T) {
|
||||
var user struct {
|
||||
Name string `ksql:"name"`
|
||||
Age int `ksql:"age"`
|
||||
}
|
||||
user.Name = "not empty"
|
||||
user.Age = 42
|
||||
|
||||
err := FillStructWith(&user, map[string]interface{}{
|
||||
"name": nil,
|
||||
"age": nil,
|
||||
})
|
||||
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, "", user.Name)
|
||||
assert.Equal(t, 0, user.Age)
|
||||
})
|
||||
|
||||
t.Run("should ignore extra or missing fields", func(t *testing.T) {
|
||||
var user struct {
|
||||
Name string `ksql:"name"`
|
||||
Age int `ksql:"age"`
|
||||
Missing string `ksql:"missing"`
|
||||
}
|
||||
user.Missing = "should be untouched"
|
||||
|
||||
err := FillStructWith(&user, map[string]interface{}{
|
||||
"name": "fake name",
|
||||
"age": 42,
|
||||
"extra_field": "some value",
|
||||
})
|
||||
|
||||
tt.AssertEqual(t, nil, err)
|
||||
tt.AssertEqual(t, "fake name", user.Name)
|
||||
tt.AssertEqual(t, 42, user.Age)
|
||||
tt.AssertEqual(t, "should be untouched", user.Missing)
|
||||
})
|
||||
|
||||
t.Run("should report error if input is not a pointer", func(t *testing.T) {
|
||||
type User struct {
|
||||
Name string `ksql:"name"`
|
||||
Age int `ksql:"age"`
|
||||
Missing string `ksql:"missing"`
|
||||
}
|
||||
var user User
|
||||
|
||||
err := FillStructWith(user, map[string]interface{}{
|
||||
"name": "fake name",
|
||||
"age": 42,
|
||||
"extra_field": "some value",
|
||||
})
|
||||
|
||||
tt.AssertErrContains(t, err, "FillStructWith", "expected input to be a pointer", "User")
|
||||
})
|
||||
|
||||
t.Run("should report error if input is not a pointer to struct", func(t *testing.T) {
|
||||
type User struct {
|
||||
Name string `ksql:"name"`
|
||||
Age int `ksql:"age"`
|
||||
Missing string `ksql:"missing"`
|
||||
}
|
||||
var users []User
|
||||
|
||||
err := FillStructWith(&users, map[string]interface{}{
|
||||
"name": "fake name",
|
||||
"age": 42,
|
||||
"extra_field": "some value",
|
||||
})
|
||||
|
||||
tt.AssertErrContains(t, err, "FillStructWith", "expected input to be a pointer to a struct", "User")
|
||||
})
|
||||
|
||||
t.Run("should report error if input and target types are incompatible", func(t *testing.T) {
|
||||
type User struct {
|
||||
Age int `ksql:"age"`
|
||||
}
|
||||
var user User
|
||||
|
||||
err := FillStructWith(&user, map[string]interface{}{
|
||||
"age": "not compatible with integer type",
|
||||
})
|
||||
|
||||
tt.AssertErrContains(t, err, "FillStructWith", "age", "string", "int")
|
||||
})
|
||||
}
|
||||
|
||||
func TestFillSliceWith(t *testing.T) {
|
||||
t.Run("should fill a list correctly", func(t *testing.T) {
|
||||
var users []struct {
|
||||
Name string `ksql:"name"`
|
||||
Age int `ksql:"age"`
|
||||
}
|
||||
err := FillSliceWith(&users, []map[string]interface{}{
|
||||
{
|
||||
"name": "Jorge",
|
||||
},
|
||||
{
|
||||
"name": "Luciana",
|
||||
},
|
||||
{
|
||||
"name": "Breno",
|
||||
},
|
||||
})
|
||||
|
||||
tt.AssertEqual(t, err, nil)
|
||||
tt.AssertEqual(t, len(users), 3)
|
||||
tt.AssertEqual(t, users[0].Name, "Jorge")
|
||||
tt.AssertEqual(t, users[1].Name, "Luciana")
|
||||
tt.AssertEqual(t, users[2].Name, "Breno")
|
||||
})
|
||||
|
||||
t.Run("should report error if input is not a pointer", func(t *testing.T) {
|
||||
var users []struct {
|
||||
Name string `ksql:"name"`
|
||||
Age int `ksql:"age"`
|
||||
}
|
||||
err := FillSliceWith(users, []map[string]interface{}{{
|
||||
"name": "Jorge",
|
||||
}})
|
||||
|
||||
tt.AssertErrContains(t, err, "FillSliceWith", "expected input to be a pointer")
|
||||
})
|
||||
|
||||
t.Run("should report error if input is not a pointer to a slice", func(t *testing.T) {
|
||||
var user struct {
|
||||
Name string `ksql:"name"`
|
||||
Age int `ksql:"age"`
|
||||
}
|
||||
err := FillSliceWith(&user, []map[string]interface{}{{
|
||||
"name": "Jorge",
|
||||
}})
|
||||
|
||||
tt.AssertErrContains(t, err, "FillSliceWith")
|
||||
})
|
||||
}
|
||||
|
||||
func TestCallFunctionWithRows(t *testing.T) {
|
||||
t.Run("should call the function correctly", func(t *testing.T) {
|
||||
type User struct {
|
||||
Name string `ksql:"name"`
|
||||
Age int `ksql:"age"`
|
||||
}
|
||||
|
||||
var inputUsers []User
|
||||
fn := func(users []User) error {
|
||||
inputUsers = users
|
||||
return nil
|
||||
}
|
||||
|
||||
err := CallFunctionWithRows(fn, []map[string]interface{}{
|
||||
{
|
||||
"name": "fake-name1",
|
||||
"age": 42,
|
||||
},
|
||||
{
|
||||
"name": "fake-name2",
|
||||
"age": 43,
|
||||
},
|
||||
})
|
||||
tt.AssertNoErr(t, err)
|
||||
tt.AssertEqual(t, inputUsers, []User{
|
||||
{
|
||||
Name: "fake-name1",
|
||||
Age: 42,
|
||||
},
|
||||
{
|
||||
Name: "fake-name2",
|
||||
Age: 43,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("should forward errors correctly", func(t *testing.T) {
|
||||
type User struct {
|
||||
Name string `ksql:"name"`
|
||||
Age int `ksql:"age"`
|
||||
}
|
||||
|
||||
fn := func(users []User) error {
|
||||
return fmt.Errorf("fake-error-msg")
|
||||
}
|
||||
|
||||
err := CallFunctionWithRows(fn, []map[string]interface{}{{
|
||||
"name": "fake-name1",
|
||||
"age": 42,
|
||||
}})
|
||||
tt.AssertErrContains(t, err, "fake-error-msg")
|
||||
})
|
||||
|
||||
t.Run("should report error if the input function is invalid", func(t *testing.T) {
|
||||
type User struct {
|
||||
Name string `ksql:"name"`
|
||||
Age int `ksql:"age"`
|
||||
}
|
||||
|
||||
err := CallFunctionWithRows(func() {}, []map[string]interface{}{{
|
||||
"name": "fake-name1",
|
||||
"age": 42,
|
||||
}})
|
||||
tt.AssertErrContains(t, err)
|
||||
})
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
// Package kstructs is deprecated: use ksqltest instead.
|
||||
package kstructs
|
||||
|
||||
import (
|
||||
|
|
Loading…
Reference in New Issue