From 5a740a6373907dafa82c2f8190c3cff7fec8f428 Mon Sep 17 00:00:00 2001 From: gedi Date: Wed, 5 Aug 2015 13:37:58 +0300 Subject: [PATCH] rows scan error mocking test --- rows.go | 11 ++++++----- rows_test.go | 22 +++++++++++++++------- sqlmock.go | 1 - 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/rows.go b/rows.go index 92ceb92..8b6beb6 100644 --- a/rows.go +++ b/rows.go @@ -8,7 +8,8 @@ import ( ) // CSVColumnParser is a function which converts trimmed csv -// column string to a []byte representation. +// column string to a []byte representation. currently +// transforms NULL to nil var CSVColumnParser = func(s string) []byte { switch { case strings.ToLower(s) == "null": @@ -54,7 +55,7 @@ type rows struct { cols []string rows [][]driver.Value pos int - scanErr map[int]error + nextErr map[int]error closeErr error } @@ -77,14 +78,14 @@ func (r *rows) Next(dest []driver.Value) error { dest[i] = col } - return r.scanErr[r.pos-1] + return r.nextErr[r.pos-1] } // NewRows allows Rows to be created from a // sql driver.Value slice or from the CSV string and // to be used as sql driver.Rows func NewRows(columns []string) Rows { - return &rows{cols: columns, scanErr: make(map[int]error)} + return &rows{cols: columns, nextErr: make(map[int]error)} } func (r *rows) CloseError(err error) Rows { @@ -93,7 +94,7 @@ func (r *rows) CloseError(err error) Rows { } func (r *rows) RowError(row int, err error) Rows { - r.scanErr[row] = err + r.nextErr[row] = err return r } diff --git a/rows_test.go b/rows_test.go index 533d880..8f11f4d 100644 --- a/rows_test.go +++ b/rows_test.go @@ -180,10 +180,7 @@ func TestQuerySingleRow(t *testing.T) { } } -// @TODO: the only way to mock columns error would be -// to return nil instead of rows, but rows.Close will -// panic due to a bug in go sql package -func TODO_TestRowsColumnsError(t *testing.T) { +func TestRowsScanError(t *testing.T) { t.Parallel() db, mock, err := New() if err != nil { @@ -191,16 +188,27 @@ func TODO_TestRowsColumnsError(t *testing.T) { } defer db.Close() - mock.ExpectQuery("SELECT").WillReturnRows(nil) + r := NewRows([]string{"col1", "col2"}).AddRow("one", "two").AddRow("one", nil) + mock.ExpectQuery("SELECT").WillReturnRows(r) rs, err := db.Query("SELECT") if err != nil { t.Fatalf("unexpected error: %s", err) } + defer rs.Close() - _, err = rs.Columns() + var one, two string + if !rs.Next() || rs.Err() != nil || rs.Scan(&one, &two) != nil { + t.Fatal("unexpected error on first row scan") + } + + if !rs.Next() || rs.Err() != nil { + t.Fatal("unexpected error on second row read") + } + + err = rs.Scan(&one, &two) if err == nil { - t.Fatal("expected an error for columns") + t.Fatal("expected an error for scan, but got none") } if err := mock.ExpectationsWereMet(); err != nil { diff --git a/sqlmock.go b/sqlmock.go index 565453a..4a44673 100644 --- a/sqlmock.go +++ b/sqlmock.go @@ -201,7 +201,6 @@ func (c *Sqlmock) Query(query string, args []driver.Value) (rw driver.Rows, err return nil, t.err // mocked to return error } - // remove when rows_test.go:186 is available, won't cause a BC if t.rows == nil { return nil, fmt.Errorf("query '%s' with args %+v, must return a database/sql/driver.rows, but it was not set for expectation %T as %+v", query, args, t, t) }