...

Source file src/github.com/DATA-DOG/go-sqlmock/rows_test.go

Documentation: github.com/DATA-DOG/go-sqlmock

     1  package sqlmock
     2  
     3  import (
     4  	"bytes"
     5  	"database/sql"
     6  	"database/sql/driver"
     7  	"fmt"
     8  	"testing"
     9  )
    10  
    11  const invalid = `☠☠☠ MEMORY OVERWRITTEN ☠☠☠ `
    12  
    13  func ExampleRows() {
    14  	db, mock, err := New()
    15  	if err != nil {
    16  		fmt.Println("failed to open sqlmock database:", err)
    17  	}
    18  	defer db.Close()
    19  
    20  	rows := NewRows([]string{"id", "title"}).
    21  		AddRow(1, "one").
    22  		AddRow(2, "two")
    23  
    24  	mock.ExpectQuery("SELECT").WillReturnRows(rows)
    25  
    26  	rs, _ := db.Query("SELECT")
    27  	defer rs.Close()
    28  
    29  	for rs.Next() {
    30  		var id int
    31  		var title string
    32  		rs.Scan(&id, &title)
    33  		fmt.Println("scanned id:", id, "and title:", title)
    34  	}
    35  
    36  	if rs.Err() != nil {
    37  		fmt.Println("got rows error:", rs.Err())
    38  	}
    39  	// Output: scanned id: 1 and title: one
    40  	// scanned id: 2 and title: two
    41  }
    42  
    43  func ExampleRows_rowError() {
    44  	db, mock, err := New()
    45  	if err != nil {
    46  		fmt.Println("failed to open sqlmock database:", err)
    47  	}
    48  	defer db.Close()
    49  
    50  	rows := NewRows([]string{"id", "title"}).
    51  		AddRow(0, "one").
    52  		AddRow(1, "two").
    53  		RowError(1, fmt.Errorf("row error"))
    54  	mock.ExpectQuery("SELECT").WillReturnRows(rows)
    55  
    56  	rs, _ := db.Query("SELECT")
    57  	defer rs.Close()
    58  
    59  	for rs.Next() {
    60  		var id int
    61  		var title string
    62  		rs.Scan(&id, &title)
    63  		fmt.Println("scanned id:", id, "and title:", title)
    64  	}
    65  
    66  	if rs.Err() != nil {
    67  		fmt.Println("got rows error:", rs.Err())
    68  	}
    69  	// Output: scanned id: 0 and title: one
    70  	// got rows error: row error
    71  }
    72  
    73  func ExampleRows_closeError() {
    74  	db, mock, err := New()
    75  	if err != nil {
    76  		fmt.Println("failed to open sqlmock database:", err)
    77  	}
    78  	defer db.Close()
    79  
    80  	rows := NewRows([]string{"id", "title"}).CloseError(fmt.Errorf("close error"))
    81  	mock.ExpectQuery("SELECT").WillReturnRows(rows)
    82  
    83  	rs, _ := db.Query("SELECT")
    84  
    85  	// Note: that close will return error only before rows EOF
    86  	// that is a default sql package behavior. If you run rs.Next()
    87  	// it will handle the error internally and return nil bellow
    88  	if err := rs.Close(); err != nil {
    89  		fmt.Println("got error:", err)
    90  	}
    91  
    92  	// Output: got error: close error
    93  }
    94  
    95  func ExampleRows_rawBytes() {
    96  	db, mock, err := New()
    97  	if err != nil {
    98  		fmt.Println("failed to open sqlmock database:", err)
    99  	}
   100  	defer db.Close()
   101  
   102  	rows := NewRows([]string{"id", "binary"}).
   103  		AddRow(1, []byte(`one binary value with some text!`)).
   104  		AddRow(2, []byte(`two binary value with even more text than the first one`))
   105  
   106  	mock.ExpectQuery("SELECT").WillReturnRows(rows)
   107  
   108  	rs, _ := db.Query("SELECT")
   109  	defer rs.Close()
   110  
   111  	type scanned struct {
   112  		id  int
   113  		raw sql.RawBytes
   114  	}
   115  	fmt.Println("initial read...")
   116  	var ss []scanned
   117  	for rs.Next() {
   118  		var s scanned
   119  		rs.Scan(&s.id, &s.raw)
   120  		ss = append(ss, s)
   121  		fmt.Println("scanned id:", s.id, "and raw:", string(s.raw))
   122  	}
   123  
   124  	if rs.Err() != nil {
   125  		fmt.Println("got rows error:", rs.Err())
   126  	}
   127  
   128  	fmt.Println("after reading all...")
   129  	for _, s := range ss {
   130  		fmt.Println("scanned id:", s.id, "and raw:", string(s.raw))
   131  	}
   132  	// Output:
   133  	// initial read...
   134  	// scanned id: 1 and raw: one binary value with some text!
   135  	// scanned id: 2 and raw: two binary value with even more text than the first one
   136  	// after reading all...
   137  	// scanned id: 1 and raw: ☠☠☠ MEMORY OVERWRITTEN ☠
   138  	// scanned id: 2 and raw: ☠☠☠ MEMORY OVERWRITTEN ☠☠☠ ☠☠☠ MEMORY
   139  }
   140  
   141  func ExampleRows_expectToBeClosed() {
   142  	db, mock, err := New()
   143  	if err != nil {
   144  		fmt.Println("failed to open sqlmock database:", err)
   145  	}
   146  	defer db.Close()
   147  
   148  	rows := NewRows([]string{"id", "title"}).AddRow(1, "john")
   149  	mock.ExpectQuery("SELECT").WillReturnRows(rows).RowsWillBeClosed()
   150  
   151  	db.Query("SELECT")
   152  
   153  	if err := mock.ExpectationsWereMet(); err != nil {
   154  		fmt.Println("got error:", err)
   155  	}
   156  
   157  	// Output: got error: expected query rows to be closed, but it was not: ExpectedQuery => expecting Query, QueryContext or QueryRow which:
   158  	//   - matches sql: 'SELECT'
   159  	//   - is without arguments
   160  	//   - should return rows:
   161  	//     row 0 - [1 john]
   162  }
   163  
   164  func ExampleRows_customDriverValue() {
   165  	db, mock, err := New()
   166  	if err != nil {
   167  		fmt.Println("failed to open sqlmock database:", err)
   168  	}
   169  	defer db.Close()
   170  
   171  	rows := NewRows([]string{"id", "null_int"}).
   172  		AddRow(1, 7).
   173  		AddRow(5, sql.NullInt64{Int64: 5, Valid: true}).
   174  		AddRow(2, sql.NullInt64{})
   175  
   176  	mock.ExpectQuery("SELECT").WillReturnRows(rows)
   177  
   178  	rs, _ := db.Query("SELECT")
   179  	defer rs.Close()
   180  
   181  	for rs.Next() {
   182  		var id int
   183  		var num sql.NullInt64
   184  		rs.Scan(&id, &num)
   185  		fmt.Println("scanned id:", id, "and null int64:", num)
   186  	}
   187  
   188  	if rs.Err() != nil {
   189  		fmt.Println("got rows error:", rs.Err())
   190  	}
   191  	// Output: scanned id: 1 and null int64: {7 true}
   192  	// scanned id: 5 and null int64: {5 true}
   193  	// scanned id: 2 and null int64: {0 false}
   194  }
   195  
   196  func TestAllowsToSetRowsErrors(t *testing.T) {
   197  	t.Parallel()
   198  	db, mock, err := New()
   199  	if err != nil {
   200  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   201  	}
   202  	defer db.Close()
   203  
   204  	rows := NewRows([]string{"id", "title"}).
   205  		AddRow(0, "one").
   206  		AddRow(1, "two").
   207  		RowError(1, fmt.Errorf("error"))
   208  	mock.ExpectQuery("SELECT").WillReturnRows(rows)
   209  
   210  	rs, err := db.Query("SELECT")
   211  	if err != nil {
   212  		t.Fatalf("unexpected error: %s", err)
   213  	}
   214  	defer rs.Close()
   215  
   216  	if !rs.Next() {
   217  		t.Fatal("expected the first row to be available")
   218  	}
   219  	if rs.Err() != nil {
   220  		t.Fatalf("unexpected error: %s", rs.Err())
   221  	}
   222  
   223  	if rs.Next() {
   224  		t.Fatal("was not expecting the second row, since there should be an error")
   225  	}
   226  	if rs.Err() == nil {
   227  		t.Fatal("expected an error, but got none")
   228  	}
   229  
   230  	if err := mock.ExpectationsWereMet(); err != nil {
   231  		t.Fatal(err)
   232  	}
   233  }
   234  
   235  func TestRowsCloseError(t *testing.T) {
   236  	t.Parallel()
   237  	db, mock, err := New()
   238  	if err != nil {
   239  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   240  	}
   241  	defer db.Close()
   242  
   243  	rows := NewRows([]string{"id"}).CloseError(fmt.Errorf("close error"))
   244  	mock.ExpectQuery("SELECT").WillReturnRows(rows)
   245  
   246  	rs, err := db.Query("SELECT")
   247  	if err != nil {
   248  		t.Fatalf("unexpected error: %s", err)
   249  	}
   250  
   251  	if err := rs.Close(); err == nil {
   252  		t.Fatal("expected a close error")
   253  	}
   254  
   255  	if err := mock.ExpectationsWereMet(); err != nil {
   256  		t.Fatal(err)
   257  	}
   258  }
   259  
   260  func TestRowsClosed(t *testing.T) {
   261  	t.Parallel()
   262  	db, mock, err := New()
   263  	if err != nil {
   264  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   265  	}
   266  	defer db.Close()
   267  
   268  	rows := NewRows([]string{"id"}).AddRow(1)
   269  	mock.ExpectQuery("SELECT").WillReturnRows(rows).RowsWillBeClosed()
   270  
   271  	rs, err := db.Query("SELECT")
   272  	if err != nil {
   273  		t.Fatalf("unexpected error: %s", err)
   274  	}
   275  
   276  	if err := rs.Close(); err != nil {
   277  		t.Fatalf("unexpected error: %v", err)
   278  	}
   279  
   280  	if err := mock.ExpectationsWereMet(); err != nil {
   281  		t.Fatal(err)
   282  	}
   283  }
   284  
   285  func TestQuerySingleRow(t *testing.T) {
   286  	t.Parallel()
   287  	db, mock, err := New()
   288  	if err != nil {
   289  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   290  	}
   291  	defer db.Close()
   292  
   293  	rows := NewRows([]string{"id"}).
   294  		AddRow(1).
   295  		AddRow(2)
   296  	mock.ExpectQuery("SELECT").WillReturnRows(rows)
   297  
   298  	var id int
   299  	if err := db.QueryRow("SELECT").Scan(&id); err != nil {
   300  		t.Fatalf("unexpected error: %s", err)
   301  	}
   302  
   303  	mock.ExpectQuery("SELECT").WillReturnRows(NewRows([]string{"id"}))
   304  	if err := db.QueryRow("SELECT").Scan(&id); err != sql.ErrNoRows {
   305  		t.Fatal("expected sql no rows error")
   306  	}
   307  
   308  	if err := mock.ExpectationsWereMet(); err != nil {
   309  		t.Fatal(err)
   310  	}
   311  }
   312  
   313  func TestQueryRowBytesInvalidatedByNext_bytesIntoRawBytes(t *testing.T) {
   314  	t.Parallel()
   315  	replace := []byte(invalid)
   316  	rows := NewRows([]string{"raw"}).
   317  		AddRow([]byte(`one binary value with some text!`)).
   318  		AddRow([]byte(`two binary value with even more text than the first one`))
   319  	scan := func(rs *sql.Rows) ([]byte, error) {
   320  		var raw sql.RawBytes
   321  		return raw, rs.Scan(&raw)
   322  	}
   323  	want := []struct {
   324  		Initial  []byte
   325  		Replaced []byte
   326  	}{
   327  		{Initial: []byte(`one binary value with some text!`), Replaced: replace[:len(replace)-7]},
   328  		{Initial: []byte(`two binary value with even more text than the first one`), Replaced: bytes.Join([][]byte{replace, replace[:len(replace)-23]}, nil)},
   329  	}
   330  	queryRowBytesInvalidatedByNext(t, rows, scan, want)
   331  }
   332  
   333  func TestQueryRowBytesNotInvalidatedByNext_bytesIntoBytes(t *testing.T) {
   334  	t.Parallel()
   335  	rows := NewRows([]string{"raw"}).
   336  		AddRow([]byte(`one binary value with some text!`)).
   337  		AddRow([]byte(`two binary value with even more text than the first one`))
   338  	scan := func(rs *sql.Rows) ([]byte, error) {
   339  		var b []byte
   340  		return b, rs.Scan(&b)
   341  	}
   342  	want := [][]byte{[]byte(`one binary value with some text!`), []byte(`two binary value with even more text than the first one`)}
   343  	queryRowBytesNotInvalidatedByNext(t, rows, scan, want)
   344  }
   345  
   346  func TestQueryRowBytesNotInvalidatedByNext_stringIntoBytes(t *testing.T) {
   347  	t.Parallel()
   348  	rows := NewRows([]string{"raw"}).
   349  		AddRow(`one binary value with some text!`).
   350  		AddRow(`two binary value with even more text than the first one`)
   351  	scan := func(rs *sql.Rows) ([]byte, error) {
   352  		var b []byte
   353  		return b, rs.Scan(&b)
   354  	}
   355  	want := [][]byte{[]byte(`one binary value with some text!`), []byte(`two binary value with even more text than the first one`)}
   356  	queryRowBytesNotInvalidatedByNext(t, rows, scan, want)
   357  }
   358  
   359  func TestQueryRowBytesInvalidatedByClose_bytesIntoRawBytes(t *testing.T) {
   360  	t.Parallel()
   361  	replace := []byte(invalid)
   362  	rows := NewRows([]string{"raw"}).AddRow([]byte(`one binary value with some text!`))
   363  	scan := func(rs *sql.Rows) ([]byte, error) {
   364  		var raw sql.RawBytes
   365  		return raw, rs.Scan(&raw)
   366  	}
   367  	want := struct {
   368  		Initial  []byte
   369  		Replaced []byte
   370  	}{
   371  		Initial:  []byte(`one binary value with some text!`),
   372  		Replaced: replace[:len(replace)-7],
   373  	}
   374  	queryRowBytesInvalidatedByClose(t, rows, scan, want)
   375  }
   376  
   377  func TestQueryRowBytesNotInvalidatedByClose_bytesIntoBytes(t *testing.T) {
   378  	t.Parallel()
   379  	rows := NewRows([]string{"raw"}).AddRow([]byte(`one binary value with some text!`))
   380  	scan := func(rs *sql.Rows) ([]byte, error) {
   381  		var b []byte
   382  		return b, rs.Scan(&b)
   383  	}
   384  	queryRowBytesNotInvalidatedByClose(t, rows, scan, []byte(`one binary value with some text!`))
   385  }
   386  
   387  func TestQueryRowBytesNotInvalidatedByClose_stringIntoBytes(t *testing.T) {
   388  	t.Parallel()
   389  	rows := NewRows([]string{"raw"}).AddRow(`one binary value with some text!`)
   390  	scan := func(rs *sql.Rows) ([]byte, error) {
   391  		var b []byte
   392  		return b, rs.Scan(&b)
   393  	}
   394  	queryRowBytesNotInvalidatedByClose(t, rows, scan, []byte(`one binary value with some text!`))
   395  }
   396  
   397  func TestRowsScanError(t *testing.T) {
   398  	t.Parallel()
   399  	db, mock, err := New()
   400  	if err != nil {
   401  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   402  	}
   403  	defer db.Close()
   404  
   405  	r := NewRows([]string{"col1", "col2"}).AddRow("one", "two").AddRow("one", nil)
   406  	mock.ExpectQuery("SELECT").WillReturnRows(r)
   407  
   408  	rs, err := db.Query("SELECT")
   409  	if err != nil {
   410  		t.Fatalf("unexpected error: %s", err)
   411  	}
   412  	defer rs.Close()
   413  
   414  	var one, two string
   415  	if !rs.Next() || rs.Err() != nil || rs.Scan(&one, &two) != nil {
   416  		t.Fatal("unexpected error on first row scan")
   417  	}
   418  
   419  	if !rs.Next() || rs.Err() != nil {
   420  		t.Fatal("unexpected error on second row read")
   421  	}
   422  
   423  	err = rs.Scan(&one, &two)
   424  	if err == nil {
   425  		t.Fatal("expected an error for scan, but got none")
   426  	}
   427  
   428  	if err := mock.ExpectationsWereMet(); err != nil {
   429  		t.Fatal(err)
   430  	}
   431  }
   432  
   433  func TestCSVRowParser(t *testing.T) {
   434  	t.Parallel()
   435  	rs := NewRows([]string{"col1", "col2", "col3"}).FromCSVString("a,NULL,NULL")
   436  	db, mock, err := New()
   437  	if err != nil {
   438  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   439  	}
   440  	defer db.Close()
   441  
   442  	mock.ExpectQuery("SELECT").WillReturnRows(rs)
   443  
   444  	rw, err := db.Query("SELECT")
   445  	if err != nil {
   446  		t.Fatalf("unexpected error: %s", err)
   447  	}
   448  	defer rw.Close()
   449  	var col1 string
   450  	var col2 []byte
   451  	var col3 *string
   452  
   453  	rw.Next()
   454  	if err = rw.Scan(&col1, &col2, &col3); err != nil {
   455  		t.Fatalf("unexpected error: %s", err)
   456  	}
   457  	if col1 != "a" {
   458  		t.Fatalf("expected col1 to be 'a', but got [%T]:%+v", col1, col1)
   459  	}
   460  	if col2 != nil {
   461  		t.Fatalf("expected col2 to be nil, but got [%T]:%+v", col2, col2)
   462  	}
   463  	if col3 != nil {
   464  		t.Fatalf("expected col3 to be nil, but got [%T]:%+v", col3, col3)
   465  	}
   466  }
   467  
   468  func TestCSVParserInvalidInput(t *testing.T) {
   469  	defer func() {
   470  		recover()
   471  	}()
   472  	_ = NewRows([]string{"col1", "col2"}).FromCSVString("a,\"NULL\"\"")
   473  	// shouldn't reach here
   474  	t.Error("expected panic from parsing invalid CSV")
   475  }
   476  
   477  func TestWrongNumberOfValues(t *testing.T) {
   478  	// Open new mock database
   479  	db, mock, err := New()
   480  	if err != nil {
   481  		fmt.Println("error creating mock database")
   482  		return
   483  	}
   484  	defer db.Close()
   485  	defer func() {
   486  		recover()
   487  	}()
   488  	mock.ExpectQuery("SELECT ID FROM TABLE").WithArgs(101).WillReturnRows(NewRows([]string{"ID"}).AddRow(101, "Hello"))
   489  	db.Query("SELECT ID FROM TABLE", 101)
   490  	// shouldn't reach here
   491  	t.Error("expected panic from query")
   492  }
   493  
   494  func TestEmptyRowSets(t *testing.T) {
   495  	rs1 := NewRows([]string{"a"}).AddRow("a")
   496  	rs2 := NewRows([]string{"b"})
   497  	rs3 := NewRows([]string{"c"})
   498  
   499  	set1 := &rowSets{sets: []*Rows{rs1, rs2}}
   500  	set2 := &rowSets{sets: []*Rows{rs3, rs2}}
   501  	set3 := &rowSets{sets: []*Rows{rs2}}
   502  
   503  	if set1.empty() {
   504  		t.Fatalf("expected rowset 1, not to be empty, but it was")
   505  	}
   506  	if !set2.empty() {
   507  		t.Fatalf("expected rowset 2, to be empty, but it was not")
   508  	}
   509  	if !set3.empty() {
   510  		t.Fatalf("expected rowset 3, to be empty, but it was not")
   511  	}
   512  }
   513  
   514  func queryRowBytesInvalidatedByNext(t *testing.T, rows *Rows, scan func(*sql.Rows) ([]byte, error), want []struct {
   515  	Initial  []byte
   516  	Replaced []byte
   517  }) {
   518  	db, mock, err := New()
   519  	if err != nil {
   520  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   521  	}
   522  	defer db.Close()
   523  	mock.ExpectQuery("SELECT").WillReturnRows(rows)
   524  
   525  	rs, err := db.Query("SELECT")
   526  	if err != nil {
   527  		t.Fatalf("failed to query rows: %s", err)
   528  	}
   529  
   530  	if !rs.Next() || rs.Err() != nil {
   531  		t.Fatal("unexpected error on first row retrieval")
   532  	}
   533  	var count int
   534  	for i := 0; ; i++ {
   535  		count++
   536  		b, err := scan(rs)
   537  		if err != nil {
   538  			t.Fatalf("unexpected error scanning row: %s", err)
   539  		}
   540  		if exp := want[i].Initial; !bytes.Equal(b, exp) {
   541  			t.Fatalf("expected raw value to be '%s' (len:%d), but got [%T]:%s (len:%d)", exp, len(exp), b, b, len(b))
   542  		}
   543  		next := rs.Next()
   544  		if exp := want[i].Replaced; !bytes.Equal(b, exp) {
   545  			t.Fatalf("expected raw value to be replaced with '%s' (len:%d) after calling Next(), but got [%T]:%s (len:%d)", exp, len(exp), b, b, len(b))
   546  		}
   547  		if !next {
   548  			break
   549  		}
   550  	}
   551  	if err := rs.Err(); err != nil {
   552  		t.Fatalf("row iteration failed: %s", err)
   553  	}
   554  	if exp := len(want); count != exp {
   555  		t.Fatalf("incorrect number of rows exp: %d, but got %d", exp, count)
   556  	}
   557  
   558  	if err := mock.ExpectationsWereMet(); err != nil {
   559  		t.Fatal(err)
   560  	}
   561  }
   562  
   563  func queryRowBytesNotInvalidatedByNext(t *testing.T, rows *Rows, scan func(*sql.Rows) ([]byte, error), want [][]byte) {
   564  	db, mock, err := New()
   565  	if err != nil {
   566  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   567  	}
   568  	defer db.Close()
   569  	mock.ExpectQuery("SELECT").WillReturnRows(rows)
   570  
   571  	rs, err := db.Query("SELECT")
   572  	if err != nil {
   573  		t.Fatalf("failed to query rows: %s", err)
   574  	}
   575  
   576  	if !rs.Next() || rs.Err() != nil {
   577  		t.Fatal("unexpected error on first row retrieval")
   578  	}
   579  	var count int
   580  	for i := 0; ; i++ {
   581  		count++
   582  		b, err := scan(rs)
   583  		if err != nil {
   584  			t.Fatalf("unexpected error scanning row: %s", err)
   585  		}
   586  		if exp := want[i]; !bytes.Equal(b, exp) {
   587  			t.Fatalf("expected raw value to be '%s' (len:%d), but got [%T]:%s (len:%d)", exp, len(exp), b, b, len(b))
   588  		}
   589  		next := rs.Next()
   590  		if exp := want[i]; !bytes.Equal(b, exp) {
   591  			t.Fatalf("expected raw value to be replaced with '%s' (len:%d) after calling Next(), but got [%T]:%s (len:%d)", exp, len(exp), b, b, len(b))
   592  		}
   593  		if !next {
   594  			break
   595  		}
   596  	}
   597  	if err := rs.Err(); err != nil {
   598  		t.Fatalf("row iteration failed: %s", err)
   599  	}
   600  	if exp := len(want); count != exp {
   601  		t.Fatalf("incorrect number of rows exp: %d, but got %d", exp, count)
   602  	}
   603  
   604  	if err := mock.ExpectationsWereMet(); err != nil {
   605  		t.Fatal(err)
   606  	}
   607  }
   608  
   609  func queryRowBytesInvalidatedByClose(t *testing.T, rows *Rows, scan func(*sql.Rows) ([]byte, error), want struct {
   610  	Initial  []byte
   611  	Replaced []byte
   612  }) {
   613  	db, mock, err := New()
   614  	if err != nil {
   615  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   616  	}
   617  	defer db.Close()
   618  	mock.ExpectQuery("SELECT").WillReturnRows(rows)
   619  
   620  	rs, err := db.Query("SELECT")
   621  	if err != nil {
   622  		t.Fatalf("failed to query rows: %s", err)
   623  	}
   624  
   625  	if !rs.Next() || rs.Err() != nil {
   626  		t.Fatal("unexpected error on first row retrieval")
   627  	}
   628  	b, err := scan(rs)
   629  	if err != nil {
   630  		t.Fatalf("unexpected error scanning row: %s", err)
   631  	}
   632  	if !bytes.Equal(b, want.Initial) {
   633  		t.Fatalf("expected raw value to be '%s' (len:%d), but got [%T]:%s (len:%d)", want.Initial, len(want.Initial), b, b, len(b))
   634  	}
   635  	if err := rs.Close(); err != nil {
   636  		t.Fatalf("unexpected error closing rows: %s", err)
   637  	}
   638  	if !bytes.Equal(b, want.Replaced) {
   639  		t.Fatalf("expected raw value to be replaced with '%s' (len:%d) after calling Next(), but got [%T]:%s (len:%d)", want.Replaced, len(want.Replaced), b, b, len(b))
   640  	}
   641  	if err := rs.Err(); err != nil {
   642  		t.Fatalf("row iteration failed: %s", err)
   643  	}
   644  
   645  	if err := mock.ExpectationsWereMet(); err != nil {
   646  		t.Fatal(err)
   647  	}
   648  }
   649  
   650  func queryRowBytesNotInvalidatedByClose(t *testing.T, rows *Rows, scan func(*sql.Rows) ([]byte, error), want []byte) {
   651  	db, mock, err := New()
   652  	if err != nil {
   653  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   654  	}
   655  	defer db.Close()
   656  	mock.ExpectQuery("SELECT").WillReturnRows(rows)
   657  
   658  	rs, err := db.Query("SELECT")
   659  	if err != nil {
   660  		t.Fatalf("failed to query rows: %s", err)
   661  	}
   662  
   663  	if !rs.Next() || rs.Err() != nil {
   664  		t.Fatal("unexpected error on first row retrieval")
   665  	}
   666  	b, err := scan(rs)
   667  	if err != nil {
   668  		t.Fatalf("unexpected error scanning row: %s", err)
   669  	}
   670  	if !bytes.Equal(b, want) {
   671  		t.Fatalf("expected raw value to be '%s' (len:%d), but got [%T]:%s (len:%d)", want, len(want), b, b, len(b))
   672  	}
   673  	if err := rs.Close(); err != nil {
   674  		t.Fatalf("unexpected error closing rows: %s", err)
   675  	}
   676  	if !bytes.Equal(b, want) {
   677  		t.Fatalf("expected raw value to be replaced with '%s' (len:%d) after calling Next(), but got [%T]:%s (len:%d)", want, len(want), b, b, len(b))
   678  	}
   679  	if err := rs.Err(); err != nil {
   680  		t.Fatalf("row iteration failed: %s", err)
   681  	}
   682  
   683  	if err := mock.ExpectationsWereMet(); err != nil {
   684  		t.Fatal(err)
   685  	}
   686  }
   687  
   688  func TestAddRows(t *testing.T) {
   689  	t.Parallel()
   690  	db, mock, err := New()
   691  	if err != nil {
   692  		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
   693  	}
   694  	defer db.Close()
   695  
   696  	values := [][]driver.Value{
   697  		{
   698  			1, "John",
   699  		},
   700  		{
   701  			2, "Jane",
   702  		},
   703  		{
   704  			3, "Peter",
   705  		},
   706  		{
   707  			4, "Emily",
   708  		},
   709  	}
   710  
   711  	rows := NewRows([]string{"id", "name"}).AddRows(values...)
   712  	mock.ExpectQuery("SELECT").WillReturnRows(rows).RowsWillBeClosed()
   713  
   714  	rs, _ := db.Query("SELECT")
   715  	defer rs.Close()
   716  
   717  	for rs.Next() {
   718  		var id int
   719  		var name string
   720  		rs.Scan(&id, &name)
   721  		fmt.Println("scanned id:", id, "and name:", name)
   722  	}
   723  
   724  	if rs.Err() != nil {
   725  		fmt.Println("got rows error:", rs.Err())
   726  	}
   727  	// Output: scanned id: 1 and title: John
   728  	// scanned id: 2 and title: Jane
   729  	// scanned id: 3 and title: Peter
   730  	// scanned id: 4 and title: Emily
   731  }
   732  
   733  func TestAddRowExpectPanic(t *testing.T) {
   734  	t.Parallel()
   735  
   736  	const expectedPanic = "Expected number of values to match number of columns: expected 1, actual 2"
   737  	values := []driver.Value{
   738  		"John",
   739  		"Jane",
   740  	}
   741  
   742  	defer func() {
   743  		if r := recover(); r != nil {
   744  			if r != expectedPanic {
   745  				t.Fatalf("panic message did not match expected: expected '%s', actual '%s'", r, expectedPanic)
   746  			}
   747  
   748  			return
   749  		}
   750  		t.Fatalf("expected panic: %s", expectedPanic)
   751  	}()
   752  
   753  	rows := NewRows([]string{"id", "name"})
   754  	// Note missing spread "..."
   755  	rows.AddRow(values)
   756  }
   757  
   758  func ExampleRows_AddRows() {
   759  	db, mock, err := New()
   760  	if err != nil {
   761  		fmt.Println("failed to open sqlmock database:", err)
   762  	}
   763  	defer db.Close()
   764  
   765  	values := [][]driver.Value{
   766  		{
   767  			1, "one",
   768  		},
   769  		{
   770  			2, "two",
   771  		},
   772  	}
   773  
   774  	rows := NewRows([]string{"id", "title"}).AddRows(values...)
   775  
   776  	mock.ExpectQuery("SELECT").WillReturnRows(rows)
   777  
   778  	rs, _ := db.Query("SELECT")
   779  	defer rs.Close()
   780  
   781  	for rs.Next() {
   782  		var id int
   783  		var title string
   784  		rs.Scan(&id, &title)
   785  		fmt.Println("scanned id:", id, "and title:", title)
   786  	}
   787  
   788  	if rs.Err() != nil {
   789  		fmt.Println("got rows error:", rs.Err())
   790  	}
   791  	// Output: scanned id: 1 and title: one
   792  	// scanned id: 2 and title: two
   793  }
   794  

View as plain text