github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/kit/sqlx/scanner/scan_test.go (about)

     1  package scanner_test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/DATA-DOG/go-sqlmock"
     8  	"github.com/onsi/gomega"
     9  
    10  	. "github.com/machinefi/w3bstream/pkg/depends/kit/sqlx/scanner"
    11  )
    12  
    13  type T struct {
    14  	I int    `db:"f_i"`
    15  	S string `db:"f_s"`
    16  }
    17  
    18  type Any string
    19  
    20  type T2 T
    21  
    22  func (t *T2) ColumnReceivers() map[string]interface{} {
    23  	return map[string]interface{}{
    24  		"f_i": &t.I,
    25  		"f_s": &t.S,
    26  	}
    27  }
    28  
    29  type TDataList struct {
    30  	Data []T
    31  }
    32  
    33  func (*TDataList) New() interface{} { return &T{} }
    34  
    35  func (l *TDataList) Next(v interface{}) error {
    36  	t := v.(*T)
    37  	l.Data = append(l.Data, *t)
    38  	return nil
    39  }
    40  
    41  func BenchmarkScan(b *testing.B) {
    42  	db, mock, _ := sqlmock.New()
    43  	defer db.Close()
    44  
    45  	b.Run("ScanToStruct", func(b *testing.B) {
    46  		query := "SELECT f_i,f_s FROM t"
    47  		_ = mock.ExpectQuery(query).
    48  			WillReturnRows(
    49  				mock.NewRows([]string{"f_i", "f_s"}).AddRow(2, "4"),
    50  			)
    51  		target := &T{}
    52  		for i := 0; i < b.N; i++ {
    53  			rows, _ := db.Query(query)
    54  			_ = Scan(context.Background(), rows, target)
    55  		}
    56  		b.Log(target)
    57  	})
    58  	b.Run("ScanToColumnReceivers", func(b *testing.B) {
    59  		sql := "SELECT f_i,f_s from t"
    60  
    61  		mockRows := mock.NewRows([]string{"f_i", "f_s"})
    62  		mockRows.AddRow(2, "4")
    63  
    64  		_ = mock.ExpectQuery(sql).WillReturnRows(mockRows)
    65  
    66  		target := &T2{}
    67  
    68  		for i := 0; i < b.N; i++ {
    69  			rows, _ := db.Query(sql)
    70  			_ = Scan(context.Background(), rows, target)
    71  		}
    72  
    73  		b.Log(target)
    74  	})
    75  }
    76  
    77  func TestScan(t *testing.T) {
    78  	db, mock, _ := sqlmock.New()
    79  	defer db.Close()
    80  
    81  	t.Run("ScanToStruct", func(t *testing.T) {
    82  		sql := "SELECT f_i,f_s from t"
    83  
    84  		mockRows := mock.NewRows([]string{"f_i", "f_s"})
    85  		mockRows.AddRow(2, "4")
    86  
    87  		_ = mock.ExpectQuery(sql).WillReturnRows(mockRows)
    88  
    89  		target := &T{}
    90  		rows, _ := db.Query(sql)
    91  		err := Scan(context.Background(), rows, target)
    92  		gomega.NewWithT(t).Expect(err).To(gomega.BeNil())
    93  		gomega.NewWithT(t).Expect(target).To(gomega.Equal(&T{
    94  			I: 2,
    95  			S: "4",
    96  		}))
    97  	})
    98  
    99  	t.Run("ScanToStructWithColumnReceivers", func(t *testing.T) {
   100  		sql := "SELECT f_i,f_s from t"
   101  
   102  		mockRows := mock.NewRows([]string{"f_i", "f_s"})
   103  		mockRows.AddRow(2, "4")
   104  
   105  		_ = mock.ExpectQuery(sql).WillReturnRows(mockRows)
   106  
   107  		target := &T2{}
   108  		rows, _ := db.Query(sql)
   109  		err := Scan(context.Background(), rows, target)
   110  		gomega.NewWithT(t).Expect(err).To(gomega.BeNil())
   111  		gomega.NewWithT(t).Expect(target).To(gomega.Equal(&T2{
   112  			I: 2,
   113  			S: "4",
   114  		}))
   115  	})
   116  
   117  	t.Run("ScanToStructWithoutNoRecord", func(t *testing.T) {
   118  		sql := "SELECT f_i,f_s from t"
   119  
   120  		mockRows := mock.NewRows([]string{"f_i", "f_s"})
   121  
   122  		_ = mock.ExpectQuery(sql).WillReturnRows(mockRows)
   123  
   124  		target := &T{}
   125  		rows, err := db.Query(sql)
   126  		gomega.NewWithT(t).Expect(err).To(gomega.BeNil())
   127  
   128  		err = Scan(context.Background(), rows, target)
   129  		gomega.NewWithT(t).Expect(err).To(gomega.Equal(RecordNotFound))
   130  	})
   131  
   132  	t.Run("Scan to count", func(t *testing.T) {
   133  		mockRows := mock.NewRows([]string{"count(1)"})
   134  		mockRows.AddRow(10)
   135  
   136  		_ = mock.ExpectQuery("SELECT .+ from t").WillReturnRows(mockRows)
   137  
   138  		count := 0
   139  		rows, err := db.Query("SELECT count(1) from t")
   140  		gomega.NewWithT(t).Expect(err).To(gomega.BeNil())
   141  
   142  		err = Scan(context.Background(), rows, &count)
   143  		gomega.NewWithT(t).Expect(err).To(gomega.BeNil())
   144  		gomega.NewWithT(t).Expect(count).To(gomega.Equal(10))
   145  	})
   146  
   147  	t.Run("ScanToCountFailedWhenBadReceiver", func(t *testing.T) {
   148  		mockRows := mock.NewRows([]string{"count(1)"})
   149  		mockRows.AddRow(10)
   150  
   151  		_ = mock.ExpectQuery("SELECT .+ from t").WillReturnRows(mockRows)
   152  
   153  		v := Any("")
   154  		rows, err := db.Query("SELECT count(1) from t")
   155  		gomega.NewWithT(t).Expect(err).To(gomega.BeNil())
   156  
   157  		err = Scan(context.Background(), rows, &v)
   158  		gomega.NewWithT(t).Expect(err).NotTo(gomega.BeNil())
   159  	})
   160  
   161  	t.Run("ScanToSlice", func(t *testing.T) {
   162  		mockRows := mock.NewRows([]string{"f_i", "f_s"})
   163  		mockRows.AddRow(2, "2")
   164  		mockRows.AddRow(3, "3")
   165  
   166  		_ = mock.ExpectQuery("SELECT .+ from t").WillReturnRows(mockRows)
   167  
   168  		list := make([]T, 0)
   169  		rows, err := db.Query("SELECT f_i,f_b from t")
   170  		gomega.NewWithT(t).Expect(err).To(gomega.BeNil())
   171  
   172  		err = Scan(context.Background(), rows, &list)
   173  
   174  		gomega.NewWithT(t).Expect(err).To(gomega.BeNil())
   175  		gomega.NewWithT(t).Expect(list).To(gomega.Equal([]T{
   176  			{
   177  				I: 2,
   178  				S: "2",
   179  			},
   180  			{
   181  				I: 3,
   182  				S: "3",
   183  			},
   184  		}))
   185  	})
   186  
   187  	t.Run("ScanToIter", func(t *testing.T) {
   188  		mockRows := mock.NewRows([]string{"f_i", "f_s"})
   189  		mockRows.AddRow(2, "2")
   190  		mockRows.AddRow(3, "3")
   191  
   192  		_ = mock.ExpectQuery("SELECT .+ from t").WillReturnRows(mockRows)
   193  
   194  		rows, err := db.Query("SELECT f_i,f_b from t")
   195  		gomega.NewWithT(t).Expect(err).To(gomega.BeNil())
   196  
   197  		list := TDataList{}
   198  
   199  		err = Scan(context.Background(), rows, &list)
   200  
   201  		gomega.NewWithT(t).Expect(err).To(gomega.BeNil())
   202  		gomega.NewWithT(t).Expect(list.Data).To(gomega.Equal([]T{
   203  			{
   204  				I: 2,
   205  				S: "2",
   206  			},
   207  			{
   208  				I: 3,
   209  				S: "3",
   210  			},
   211  		}))
   212  	})
   213  }