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
40
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
70
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
86
87
88 if err := rs.Close(); err != nil {
89 fmt.Println("got error:", err)
90 }
91
92
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
133
134
135
136
137
138
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
158
159
160
161
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
192
193
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
474 t.Error("expected panic from parsing invalid CSV")
475 }
476
477 func TestWrongNumberOfValues(t *testing.T) {
478
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
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
728
729
730
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
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
792
793 }
794
View as plain text