master
go 116 lines 3.54 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package sqlquery
4
5 import (
6 "context"
7 "errors"
8 "testing"
9
10 "github.com/DATA-DOG/go-sqlmock"
11 "github.com/stretchr/testify/assert"
12 "github.com/stretchr/testify/require"
13 )
14
15 func TestQueryRows(t *testing.T) {
16 t.Run("streams rows with rowEnd markers", func(t *testing.T) {
17 db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
18 require.NoError(t, err)
19 defer func() { _ = db.Close() }()
20
21 mock.ExpectQuery("SELECT a, b").
22 WillReturnRows(sqlmock.NewRows([]string{"a", "b"}).
23 AddRow("x", "1").
24 AddRow("y", "2"))
25
26 var got []struct {
27 column string
28 value string
29 rowEnd bool
30 }
31 dur, err := QueryRows(context.Background(), db, "SELECT a, b", func(column, value string, rowEnd bool) {
32 got = append(got, struct {
33 column string
34 value string
35 rowEnd bool
36 }{column: column, value: value, rowEnd: rowEnd})
37 })
38 require.NoError(t, err)
39 assert.GreaterOrEqual(t, dur.Milliseconds(), int64(0))
40
41 require.Len(t, got, 4)
42 assert.Equal(t, "a", got[0].column)
43 assert.Equal(t, "x", got[0].value)
44 assert.False(t, got[0].rowEnd)
45 assert.Equal(t, "b", got[1].column)
46 assert.Equal(t, "1", got[1].value)
47 assert.True(t, got[1].rowEnd)
48 assert.Equal(t, "a", got[2].column)
49 assert.Equal(t, "y", got[2].value)
50 assert.False(t, got[2].rowEnd)
51 assert.Equal(t, "b", got[3].column)
52 assert.Equal(t, "2", got[3].value)
53 assert.True(t, got[3].rowEnd)
54 assert.NoError(t, mock.ExpectationsWereMet())
55 })
56
57 t.Run("null values are converted to empty string", func(t *testing.T) {
58 db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
59 require.NoError(t, err)
60 defer func() { _ = db.Close() }()
61
62 mock.ExpectQuery("SELECT a").
63 WillReturnRows(sqlmock.NewRows([]string{"a"}).AddRow(nil))
64
65 var values []string
66 _, err = QueryRows(context.Background(), db, "SELECT a", func(_ string, value string, _ bool) {
67 values = append(values, value)
68 })
69 require.NoError(t, err)
70 require.Len(t, values, 1)
71 assert.Equal(t, "", values[0])
72 assert.NoError(t, mock.ExpectationsWereMet())
73 })
74
75 t.Run("nil callback is accepted", func(t *testing.T) {
76 db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
77 require.NoError(t, err)
78 defer func() { _ = db.Close() }()
79
80 mock.ExpectQuery("SELECT a").
81 WillReturnRows(sqlmock.NewRows([]string{"a"}).AddRow("x"))
82
83 _, err = QueryRows(context.Background(), db, "SELECT a", nil)
84 require.NoError(t, err)
85 assert.NoError(t, mock.ExpectationsWereMet())
86 })
87
88 t.Run("query error is propagated", func(t *testing.T) {
89 db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
90 require.NoError(t, err)
91 defer func() { _ = db.Close() }()
92
93 qerr := errors.New("query failed")
94 mock.ExpectQuery("SELECT bad").WillReturnError(qerr)
95
96 _, err = QueryRows(context.Background(), db, "SELECT bad", func(_, _ string, _ bool) {})
97 require.Error(t, err)
98 assert.ErrorIs(t, err, qerr)
99 assert.NoError(t, mock.ExpectationsWereMet())
100 })
101
102 t.Run("rows error is propagated", func(t *testing.T) {
103 db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
104 require.NoError(t, err)
105 defer func() { _ = db.Close() }()
106
107 rerr := errors.New("rows failed")
108 mock.ExpectQuery("SELECT a").
109 WillReturnRows(sqlmock.NewRows([]string{"a"}).AddRow("x").RowError(0, rerr))
110
111 _, err = QueryRows(context.Background(), db, "SELECT a", func(_, _ string, _ bool) {})
112 require.Error(t, err)
113 assert.ErrorIs(t, err, rerr)
114 assert.NoError(t, mock.ExpectationsWereMet())
115 })
116 }