Add tests with slice of pointers for the Query function

pull/2/head
Vinícius Garcia 2021-02-26 22:13:15 -03:00
parent 304e5bde49
commit f0e5674e79
2 changed files with 153 additions and 73 deletions

View File

@ -141,7 +141,13 @@ func (c DB) Query(
slice = reflect.Append(slice, elemValue) slice = reflect.Append(slice, elemValue)
} }
err = scanRows(rows, slice.Index(idx).Addr().Interface()) elemPtr := slice.Index(idx).Addr()
if isSliceOfPtrs {
// This is necessary since scanRows expects a *record not a **record
elemPtr = elemPtr.Elem()
}
err = scanRows(rows, elemPtr.Interface())
if err != nil { if err != nil {
return err return err
} }
@ -729,14 +735,14 @@ func scanRows(rows *sql.Rows, record interface{}) error {
v := reflect.ValueOf(record) v := reflect.ValueOf(record)
t := v.Type() t := v.Type()
if t.Kind() != reflect.Ptr { if t.Kind() != reflect.Ptr {
return fmt.Errorf("kissorm: expected to receive a pointer to struct, but got: %T", record) return fmt.Errorf("kissorm: expected record to be a pointer to struct, but got: %T", record)
} }
v = v.Elem() v = v.Elem()
t = t.Elem() t = t.Elem()
if t.Kind() != reflect.Struct { if t.Kind() != reflect.Struct {
return fmt.Errorf("kissorm: expected to receive a pointer to slice of structs, but got: %T", record) return fmt.Errorf("kissorm: expected record to be a pointer to struct, but got: %T", record)
} }
info := structs.GetTagInfo(t) info := structs.GetTagInfo(t)

View File

@ -23,93 +23,167 @@ type User struct {
func TestQuery(t *testing.T) { func TestQuery(t *testing.T) {
for _, driver := range []string{"sqlite3", "postgres"} { for _, driver := range []string{"sqlite3", "postgres"} {
t.Run(driver, func(t *testing.T) { t.Run(driver, func(t *testing.T) {
err := createTable(driver) t.Run("using slice of structs", func(t *testing.T) {
if err != nil { err := createTable(driver)
t.Fatal("could not create test table!, reason:", err.Error()) if err != nil {
} t.Fatal("could not create test table!, reason:", err.Error())
}
t.Run("should return 0 results correctly", func(t *testing.T) { t.Run("should return 0 results correctly", func(t *testing.T) {
db := connectDB(t, driver) db := connectDB(t, driver)
defer db.Close() defer db.Close()
ctx := context.Background() ctx := context.Background()
c := newTestDB(db, driver, "users") c := newTestDB(db, driver, "users")
var users []User var users []User
err := c.Query(ctx, &users, `SELECT * FROM users WHERE id=1;`) err := c.Query(ctx, &users, `SELECT * FROM users WHERE id=1;`)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
assert.Equal(t, []User(nil), users) assert.Equal(t, []User(nil), users)
users = []User{} users = []User{}
err = c.Query(ctx, &users, `SELECT * FROM users WHERE id=1;`) err = c.Query(ctx, &users, `SELECT * FROM users WHERE id=1;`)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
assert.Equal(t, []User{}, users) assert.Equal(t, []User{}, users)
})
t.Run("should return a user correctly", func(t *testing.T) {
db := connectDB(t, driver)
defer db.Close()
_, err := db.Exec(`INSERT INTO users (name, age) VALUES ('Bia', 0)`)
assert.Equal(t, nil, err)
ctx := context.Background()
c := newTestDB(db, driver, "users")
var users []User
err = c.Query(ctx, &users, `SELECT * FROM users WHERE name=`+c.dialect.Placeholder(0), "Bia")
assert.Equal(t, nil, err)
assert.Equal(t, 1, len(users))
assert.Equal(t, "Bia", users[0].Name)
assert.NotEqual(t, uint(0), users[0].ID)
})
t.Run("should return multiple users correctly", func(t *testing.T) {
db := connectDB(t, driver)
defer db.Close()
_, err := db.Exec(`INSERT INTO users (name, age) VALUES ('João Garcia', 0)`)
assert.Equal(t, nil, err)
_, err = db.Exec(`INSERT INTO users (name, age) VALUES ('Bia Garcia', 0)`)
assert.Equal(t, nil, err)
ctx := context.Background()
c := newTestDB(db, driver, "users")
var users []User
err = c.Query(ctx, &users, `SELECT * FROM users WHERE name like `+c.dialect.Placeholder(0), "% Garcia")
assert.Equal(t, nil, err)
assert.Equal(t, 2, len(users))
assert.Equal(t, "João Garcia", users[0].Name)
assert.NotEqual(t, uint(0), users[0].ID)
assert.Equal(t, "Bia Garcia", users[1].Name)
assert.NotEqual(t, uint(0), users[1].ID)
})
}) })
t.Run("should return a user correctly", func(t *testing.T) { t.Run("using slice of pointers to structs", func(t *testing.T) {
db := connectDB(t, driver) err := createTable(driver)
defer db.Close() if err != nil {
t.Fatal("could not create test table!, reason:", err.Error())
}
_, err := db.Exec(`INSERT INTO users (name, age) VALUES ('Bia', 0)`) t.Run("should return 0 results correctly", func(t *testing.T) {
assert.Equal(t, nil, err) db := connectDB(t, driver)
defer db.Close()
ctx := context.Background() ctx := context.Background()
c := newTestDB(db, driver, "users") c := newTestDB(db, driver, "users")
var users []User var users []*User
err = c.Query(ctx, &users, `SELECT * FROM users WHERE name=`+c.dialect.Placeholder(0), "Bia") err := c.Query(ctx, &users, `SELECT * FROM users WHERE id=1;`)
assert.Equal(t, nil, err)
assert.Equal(t, []*User(nil), users)
assert.Equal(t, nil, err) users = []*User{}
assert.Equal(t, 1, len(users)) err = c.Query(ctx, &users, `SELECT * FROM users WHERE id=1;`)
assert.Equal(t, "Bia", users[0].Name) assert.Equal(t, nil, err)
assert.NotEqual(t, uint(0), users[0].ID) assert.Equal(t, []*User{}, users)
})
t.Run("should return a user correctly", func(t *testing.T) {
db := connectDB(t, driver)
defer db.Close()
_, err := db.Exec(`INSERT INTO users (name, age) VALUES ('Bia', 0)`)
assert.Equal(t, nil, err)
ctx := context.Background()
c := newTestDB(db, driver, "users")
var users []*User
err = c.Query(ctx, &users, `SELECT * FROM users WHERE name=`+c.dialect.Placeholder(0), "Bia")
assert.Equal(t, nil, err)
assert.Equal(t, 1, len(users))
assert.Equal(t, "Bia", users[0].Name)
assert.NotEqual(t, uint(0), users[0].ID)
})
t.Run("should return multiple users correctly", func(t *testing.T) {
db := connectDB(t, driver)
defer db.Close()
_, err := db.Exec(`INSERT INTO users (name, age) VALUES ('João Garcia', 0)`)
assert.Equal(t, nil, err)
_, err = db.Exec(`INSERT INTO users (name, age) VALUES ('Bia Garcia', 0)`)
assert.Equal(t, nil, err)
ctx := context.Background()
c := newTestDB(db, driver, "users")
var users []*User
err = c.Query(ctx, &users, `SELECT * FROM users WHERE name like `+c.dialect.Placeholder(0), "% Garcia")
assert.Equal(t, nil, err)
assert.Equal(t, 2, len(users))
assert.Equal(t, "João Garcia", users[0].Name)
assert.NotEqual(t, uint(0), users[0].ID)
assert.Equal(t, "Bia Garcia", users[1].Name)
assert.NotEqual(t, uint(0), users[1].ID)
})
}) })
t.Run("should return multiple users correctly", func(t *testing.T) { t.Run("testing error cases", func(t *testing.T) {
db := connectDB(t, driver) err := createTable(driver)
defer db.Close() if err != nil {
t.Fatal("could not create test table!, reason:", err.Error())
}
_, err := db.Exec(`INSERT INTO users (name, age) VALUES ('João Garcia', 0)`) t.Run("should report error if input is not a pointer to a slice of structs", func(t *testing.T) {
assert.Equal(t, nil, err) db := connectDB(t, driver)
defer db.Close()
_, err = db.Exec(`INSERT INTO users (name, age) VALUES ('Bia Garcia', 0)`) _, err := db.Exec(`INSERT INTO users (name, age) VALUES ('Andréa Sá', 0)`)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
ctx := context.Background() _, err = db.Exec(`INSERT INTO users (name, age) VALUES ('Caio Sá', 0)`)
c := newTestDB(db, driver, "users") assert.Equal(t, nil, err)
var users []User
err = c.Query(ctx, &users, `SELECT * FROM users WHERE name like `+c.dialect.Placeholder(0), "% Garcia")
assert.Equal(t, nil, err) ctx := context.Background()
assert.Equal(t, 2, len(users)) c := newTestDB(db, "postgres", "users")
assert.Equal(t, "João Garcia", users[0].Name) err = c.Query(ctx, &User{}, `SELECT * FROM users WHERE name like `+c.dialect.Placeholder(0), "% Sá")
assert.NotEqual(t, uint(0), users[0].ID) assert.NotEqual(t, nil, err)
assert.Equal(t, "Bia Garcia", users[1].Name)
assert.NotEqual(t, uint(0), users[1].ID)
})
t.Run("should report error if input is not a pointer to a slice of structs", func(t *testing.T) { err = c.Query(ctx, []*User{}, `SELECT * FROM users WHERE name like `+c.dialect.Placeholder(0), "% Sá")
db := connectDB(t, driver) assert.NotEqual(t, nil, err)
defer db.Close()
_, err := db.Exec(`INSERT INTO users (name, age) VALUES ('Andréa Sá', 0)`) var i int
assert.Equal(t, nil, err) err = c.Query(ctx, &i, `SELECT * FROM users WHERE name like `+c.dialect.Placeholder(0), "% Sá")
assert.NotEqual(t, nil, err)
_, err = db.Exec(`INSERT INTO users (name, age) VALUES ('Caio Sá', 0)`) err = c.Query(ctx, &[]int{}, `SELECT * FROM users WHERE name like `+c.dialect.Placeholder(0), "% Sá")
assert.Equal(t, nil, err) assert.NotEqual(t, nil, err)
})
ctx := context.Background()
c := newTestDB(db, "postgres", "users")
err = c.Query(ctx, &User{}, `SELECT * FROM users WHERE name like `+c.dialect.Placeholder(0), "% Sá")
assert.NotEqual(t, nil, err)
err = c.Query(ctx, []User{}, `SELECT * FROM users WHERE name like `+c.dialect.Placeholder(0), "% Sá")
assert.NotEqual(t, nil, err)
var i int
err = c.Query(ctx, &i, `SELECT * FROM users WHERE name like `+c.dialect.Placeholder(0), "% Sá")
assert.NotEqual(t, nil, err)
err = c.Query(ctx, &[]int{}, `SELECT * FROM users WHERE name like `+c.dialect.Placeholder(0), "% Sá")
assert.NotEqual(t, nil, err)
}) })
}) })
} }