You've already forked go-sqlxmock
							
							
				mirror of
				https://github.com/zhashkevych/go-sqlxmock.git
				synced 2025-10-30 23:27:38 +02:00 
			
		
		
		
	add test for row builder and NilType based row values
This commit is contained in:
		| @@ -318,3 +318,89 @@ func TestExecExpectations(t *testing.T) { | ||||
| 		t.Errorf("error '%s' was not expected while closing the database", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestRowBuilderAndNilTypes(t *testing.T) { | ||||
| 	db, err := sql.Open("mock", "") | ||||
| 	if err != nil { | ||||
| 		t.Errorf("an error '%s' was not expected when opening a stub database connection", err) | ||||
| 	} | ||||
|  | ||||
| 	rs := NewRows([]string{"id", "active", "created", "status"}). | ||||
| 		AddRow(1, true, time.Now(), 5). | ||||
| 		AddRow(2, false, nil, nil) | ||||
|  | ||||
| 	ExpectQuery("SELECT (.+) FROM sales").WillReturnRows(rs) | ||||
|  | ||||
| 	rows, err := db.Query("SELECT * FROM sales") | ||||
| 	if err != nil { | ||||
| 		t.Errorf("error '%s' was not expected while retrieving mock rows", err) | ||||
| 	} | ||||
| 	defer rows.Close() | ||||
|  | ||||
| 	// NullTime and NullInt are used from stubs_test.go | ||||
| 	var ( | ||||
| 		id      int | ||||
| 		active  bool | ||||
| 		created NullTime | ||||
| 		status  NullInt | ||||
| 	) | ||||
|  | ||||
| 	if !rows.Next() { | ||||
| 		t.Error("it must have had row in rows, but got empty result set instead") | ||||
| 	} | ||||
|  | ||||
| 	err = rows.Scan(&id, &active, &created, &status) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("error '%s' was not expected while trying to scan row", err) | ||||
| 	} | ||||
|  | ||||
| 	if id != 1 { | ||||
| 		t.Errorf("expected mocked id to be 1, but got %d instead", id) | ||||
| 	} | ||||
|  | ||||
| 	if !active { | ||||
| 		t.Errorf("expected 'active' to be 'true', but got '%v' instead", active) | ||||
| 	} | ||||
|  | ||||
| 	if !created.Valid { | ||||
| 		t.Errorf("expected 'created' to be valid, but it %+v is not", created) | ||||
| 	} | ||||
|  | ||||
| 	if !status.Valid { | ||||
| 		t.Errorf("expected 'status' to be valid, but it %+v is not", status) | ||||
| 	} | ||||
|  | ||||
| 	if status.Integer != 5 { | ||||
| 		t.Errorf("expected 'status' to be '5', but got '%d'", status.Integer) | ||||
| 	} | ||||
|  | ||||
| 	// test second row | ||||
| 	if !rows.Next() { | ||||
| 		t.Error("it must have had row in rows, but got empty result set instead") | ||||
| 	} | ||||
|  | ||||
| 	err = rows.Scan(&id, &active, &created, &status) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("error '%s' was not expected while trying to scan row", err) | ||||
| 	} | ||||
|  | ||||
| 	if id != 2 { | ||||
| 		t.Errorf("expected mocked id to be 2, but got %d instead", id) | ||||
| 	} | ||||
|  | ||||
| 	if active { | ||||
| 		t.Errorf("expected 'active' to be 'false', but got '%v' instead", active) | ||||
| 	} | ||||
|  | ||||
| 	if created.Valid { | ||||
| 		t.Errorf("expected 'created' to be invalid, but it %+v is not", created) | ||||
| 	} | ||||
|  | ||||
| 	if status.Valid { | ||||
| 		t.Errorf("expected 'status' to be invalid, but it %+v is not", status) | ||||
| 	} | ||||
|  | ||||
| 	if err = db.Close(); err != nil { | ||||
| 		t.Errorf("error '%s' was not expected while closing the database", err) | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										76
									
								
								stubs_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								stubs_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| package sqlmock | ||||
|  | ||||
| import ( | ||||
| 	"database/sql/driver" | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| type NullTime struct { | ||||
| 	Time  time.Time | ||||
| 	Valid bool // Valid is true if Time is not NULL | ||||
| } | ||||
|  | ||||
| type NullInt struct { | ||||
| 	Integer int | ||||
| 	Valid   bool | ||||
| } | ||||
|  | ||||
| // Satisfy sql.Scanner interface | ||||
| func (ni *NullInt) Scan(value interface{}) (err error) { | ||||
| 	if value == nil { | ||||
| 		ni.Integer, ni.Valid = 0, false | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	switch v := value.(type) { | ||||
| 	case int, int8, int16, int32, int64: | ||||
| 		ni.Integer, ni.Valid = v.(int), true | ||||
| 		return | ||||
| 	case []byte: | ||||
| 		ni.Integer, err = strconv.Atoi(string(v)) | ||||
| 		ni.Valid = (err == nil) | ||||
| 		return | ||||
| 	case string: | ||||
| 		ni.Integer, err = strconv.Atoi(v) | ||||
| 		ni.Valid = (err == nil) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	ni.Valid = false | ||||
| 	return fmt.Errorf("Can't convert %T to integer", value) | ||||
| } | ||||
|  | ||||
| // Satisfy sql.Valuer interface. | ||||
| func (ni NullInt) Value() (driver.Value, error) { | ||||
| 	if !ni.Valid { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 	return ni.Integer, nil | ||||
| } | ||||
|  | ||||
| // Satisfy sql.Scanner interface | ||||
| func (nt *NullTime) Scan(value interface{}) (err error) { | ||||
| 	if value == nil { | ||||
| 		nt.Time, nt.Valid = time.Time{}, false | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	switch v := value.(type) { | ||||
| 	case time.Time: | ||||
| 		nt.Time, nt.Valid = v, true | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	nt.Valid = false | ||||
| 	return fmt.Errorf("Can't convert %T to time.Time", value) | ||||
| } | ||||
|  | ||||
| // Satisfy sql.Valuer interface. | ||||
| func (nt NullTime) Value() (driver.Value, error) { | ||||
| 	if !nt.Valid { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 	return nt.Time, nil | ||||
| } | ||||
		Reference in New Issue
	
	Block a user