From 6099e2fbb44743aebbff5a73b9a357cefd812c27 Mon Sep 17 00:00:00 2001 From: Benjamin Rupp Date: Wed, 25 Sep 2019 09:11:30 -0400 Subject: [PATCH 1/5] Adding unit tests for Query/Scan and Exec mocking, using custom []string data type --- expectations_test.go | 92 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/expectations_test.go b/expectations_test.go index 8d2f6d7..facf43c 100644 --- a/expectations_test.go +++ b/expectations_test.go @@ -1,8 +1,11 @@ package sqlmock import ( + "context" "database/sql/driver" + "errors" "fmt" + "reflect" "testing" "time" ) @@ -137,3 +140,92 @@ func TestBuildQuery(t *testing.T) { t.Error(err) } } + +type CustomConverter struct{} + +func (s CustomConverter) ConvertValue(v interface{}) (driver.Value, error) { + switch v.(type) { + case string: + return v.(string), nil + case []string: + return v.([]string), nil + case int: + return v.(int), nil + default: + return nil, errors.New(fmt.Sprintf("cannot convert %T with value %v", v, v)) + } +} +func TestCustomValueConverterQueryScan(t *testing.T) { + db, mock, _ := New(ValueConverterOption(CustomConverter{})) + query := ` + SELECT + name, + email, + address, + anotherfield + FROM user + where + name = 'John' + and + address = 'Jakarta' + + ` + expectedStringValue := "ValueOne" + expectedIntValue := 2 + expectedArrayValue := []string{"Three", "Four"} + mock.ExpectQuery(query).WillReturnRows(mock.NewRows([]string{"One", "Two", "Three"}).AddRow(expectedStringValue, expectedIntValue, []string{"Three", "Four"})) + row := db.QueryRow(query) + var stringValue string + var intValue int + var arrayValue []string + if e := row.Scan(&stringValue, &intValue, &arrayValue); e != nil { + t.Error(e) + } + if stringValue != expectedStringValue { + t.Errorf("Expectation %s does not met: %s", expectedStringValue, stringValue) + } + if intValue != expectedIntValue { + t.Errorf("Expectation %d does not met: %d", expectedIntValue, intValue) + } + if !reflect.DeepEqual(expectedArrayValue, arrayValue) { + t.Errorf("Expectation %v does not met: %v", expectedArrayValue, arrayValue) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Error(err) + } +} + +func TestCustomValueConverterExec(t *testing.T) { + db, mock, _ := New(ValueConverterOption(CustomConverter{})) + expectedQuery := "INSERT INTO tags \\(name,email,age,hobbies\\) VALUES \\(\\?,\\?,\\?,\\?\\)" + query := "INSERT INTO tags (name,email,age,hobbies) VALUES (?,?,?,?)" + name := "John" + email := "j@jj.j" + age := 12 + hobbies := []string{"soccer", "netflix"} + mock.ExpectBegin() + mock.ExpectPrepare(expectedQuery) + mock.ExpectExec(expectedQuery).WithArgs(name, email, age, hobbies).WillReturnResult(NewResult(1, 1)) + mock.ExpectCommit() + + ctx := context.Background() + tx, e := db.BeginTx(ctx, nil) + if e != nil { + t.Error(e) + return + } + stmt, e := db.PrepareContext(ctx, query) + if e != nil { + t.Error(e) + return + } + _, e = stmt.Exec(name, email, age, hobbies) + if e != nil { + t.Error(e) + return + } + tx.Commit() + if err := mock.ExpectationsWereMet(); err != nil { + t.Error(err) + } +} From 327ae5dcb6eb65b1ea7b92bf955ac80d90f5aaf5 Mon Sep 17 00:00:00 2001 From: Benjamin Rupp Date: Wed, 25 Sep 2019 09:13:06 -0400 Subject: [PATCH 2/5] Fix for mocking Exec with custom []string datatype --- expectations_go18.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/expectations_go18.go b/expectations_go18.go index 2d5ccba..6ee8adf 100644 --- a/expectations_go18.go +++ b/expectations_go18.go @@ -4,7 +4,6 @@ package sqlmock import ( "database/sql" - "database/sql/driver" "fmt" "reflect" ) @@ -54,10 +53,6 @@ func (e *queryBasedExpectation) argsMatches(args []namedValue) error { return fmt.Errorf("could not convert %d argument %T - %+v to driver value: %s", k, e.args[k], e.args[k], err) } - if !driver.IsValue(darg) { - return fmt.Errorf("argument %d: non-subset type %T returned from Value", k, darg) - } - if !reflect.DeepEqual(darg, v.Value) { return fmt.Errorf("argument %d expected [%T - %+v] does not match actual [%T - %+v]", k, darg, darg, v.Value, v.Value) } From 4567d0a67086f2956a8bc997516d49f18805fa26 Mon Sep 17 00:00:00 2001 From: Benjamin Rupp Date: Wed, 25 Sep 2019 09:25:15 -0400 Subject: [PATCH 3/5] Adjusting < go 1.8 implementation --- expectations_before_go18.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/expectations_before_go18.go b/expectations_before_go18.go index e368e04..11036a8 100644 --- a/expectations_before_go18.go +++ b/expectations_before_go18.go @@ -3,7 +3,6 @@ package sqlmock import ( - "database/sql/driver" "fmt" "reflect" ) @@ -40,10 +39,6 @@ func (e *queryBasedExpectation) argsMatches(args []namedValue) error { return fmt.Errorf("could not convert %d argument %T - %+v to driver value: %s", k, e.args[k], e.args[k], err) } - if !driver.IsValue(darg) { - return fmt.Errorf("argument %d: non-subset type %T returned from Value", k, darg) - } - if !reflect.DeepEqual(darg, v.Value) { return fmt.Errorf("argument %d expected [%T - %+v] does not match actual [%T - %+v]", k, darg, darg, v.Value, v.Value) } From cb3e425163c4408de5bd7b578fde45300d6de9e8 Mon Sep 17 00:00:00 2001 From: Benjamin Rupp Date: Wed, 25 Sep 2019 10:33:09 -0400 Subject: [PATCH 4/5] Moving Exec(...) test to 1.9 build as NamedValueChecker is only supported since 1.9 --- expectations_before_go18.go | 5 +++++ expectations_go19_test.go | 43 +++++++++++++++++++++++++++++++++++++ expectations_test.go | 38 +------------------------------- 3 files changed, 49 insertions(+), 37 deletions(-) create mode 100644 expectations_go19_test.go diff --git a/expectations_before_go18.go b/expectations_before_go18.go index 11036a8..e368e04 100644 --- a/expectations_before_go18.go +++ b/expectations_before_go18.go @@ -3,6 +3,7 @@ package sqlmock import ( + "database/sql/driver" "fmt" "reflect" ) @@ -39,6 +40,10 @@ func (e *queryBasedExpectation) argsMatches(args []namedValue) error { return fmt.Errorf("could not convert %d argument %T - %+v to driver value: %s", k, e.args[k], e.args[k], err) } + if !driver.IsValue(darg) { + return fmt.Errorf("argument %d: non-subset type %T returned from Value", k, darg) + } + if !reflect.DeepEqual(darg, v.Value) { return fmt.Errorf("argument %d expected [%T - %+v] does not match actual [%T - %+v]", k, darg, darg, v.Value, v.Value) } diff --git a/expectations_go19_test.go b/expectations_go19_test.go new file mode 100644 index 0000000..4ea5f04 --- /dev/null +++ b/expectations_go19_test.go @@ -0,0 +1,43 @@ +// +build go1.9 + +package sqlmock + +import ( + "context" + "testing" +) + +func TestCustomValueConverterExec(t *testing.T) { + db, mock, _ := New(ValueConverterOption(CustomConverter{})) + expectedQuery := "INSERT INTO tags \\(name,email,age,hobbies\\) VALUES \\(\\?,\\?,\\?,\\?\\)" + query := "INSERT INTO tags (name,email,age,hobbies) VALUES (?,?,?,?)" + name := "John" + email := "j@jj.j" + age := 12 + hobbies := []string{"soccer", "netflix"} + mock.ExpectBegin() + mock.ExpectPrepare(expectedQuery) + mock.ExpectExec(expectedQuery).WithArgs(name, email, age, hobbies).WillReturnResult(NewResult(1, 1)) + mock.ExpectCommit() + + ctx := context.Background() + tx, e := db.BeginTx(ctx, nil) + if e != nil { + t.Error(e) + return + } + stmt, e := db.PrepareContext(ctx, query) + if e != nil { + t.Error(e) + return + } + _, e = stmt.Exec(name, email, age, hobbies) + if e != nil { + t.Error(e) + return + } + tx.Commit() + if err := mock.ExpectationsWereMet(); err != nil { + t.Error(err) + } +} diff --git a/expectations_test.go b/expectations_test.go index facf43c..09e0441 100644 --- a/expectations_test.go +++ b/expectations_test.go @@ -1,7 +1,6 @@ package sqlmock import ( - "context" "database/sql/driver" "errors" "fmt" @@ -193,39 +192,4 @@ func TestCustomValueConverterQueryScan(t *testing.T) { if err := mock.ExpectationsWereMet(); err != nil { t.Error(err) } -} - -func TestCustomValueConverterExec(t *testing.T) { - db, mock, _ := New(ValueConverterOption(CustomConverter{})) - expectedQuery := "INSERT INTO tags \\(name,email,age,hobbies\\) VALUES \\(\\?,\\?,\\?,\\?\\)" - query := "INSERT INTO tags (name,email,age,hobbies) VALUES (?,?,?,?)" - name := "John" - email := "j@jj.j" - age := 12 - hobbies := []string{"soccer", "netflix"} - mock.ExpectBegin() - mock.ExpectPrepare(expectedQuery) - mock.ExpectExec(expectedQuery).WithArgs(name, email, age, hobbies).WillReturnResult(NewResult(1, 1)) - mock.ExpectCommit() - - ctx := context.Background() - tx, e := db.BeginTx(ctx, nil) - if e != nil { - t.Error(e) - return - } - stmt, e := db.PrepareContext(ctx, query) - if e != nil { - t.Error(e) - return - } - _, e = stmt.Exec(name, email, age, hobbies) - if e != nil { - t.Error(e) - return - } - tx.Commit() - if err := mock.ExpectationsWereMet(); err != nil { - t.Error(err) - } -} +} \ No newline at end of file From 181c3c5c8e477a216eb220616e609283ea66b83a Mon Sep 17 00:00:00 2001 From: Benjamin Rupp Date: Wed, 25 Sep 2019 10:45:27 -0400 Subject: [PATCH 5/5] Fix go fmt --- expectations_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/expectations_test.go b/expectations_test.go index 09e0441..c6889c3 100644 --- a/expectations_test.go +++ b/expectations_test.go @@ -192,4 +192,4 @@ func TestCustomValueConverterQueryScan(t *testing.T) { if err := mock.ExpectationsWereMet(); err != nil { t.Error(err) } -} \ No newline at end of file +}