You've already forked go-sqlmock
							
							
				mirror of
				https://github.com/DATA-DOG/go-sqlmock.git
				synced 2025-10-30 23:47:46 +02:00 
			
		
		
		
	do not expose sql driver methods for sqlmock, give interface
This commit is contained in:
		
							
								
								
									
										12
									
								
								driver.go
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								driver.go
									
									
									
									
									
								
							| @@ -11,7 +11,7 @@ var pool *mockDriver | ||||
|  | ||||
| func init() { | ||||
| 	pool = &mockDriver{ | ||||
| 		conns: make(map[string]*Sqlmock), | ||||
| 		conns: make(map[string]*sqlmock), | ||||
| 	} | ||||
| 	sql.Register("sqlmock", pool) | ||||
| } | ||||
| @@ -19,7 +19,7 @@ func init() { | ||||
| type mockDriver struct { | ||||
| 	sync.Mutex | ||||
| 	counter int | ||||
| 	conns   map[string]*Sqlmock | ||||
| 	conns   map[string]*sqlmock | ||||
| } | ||||
|  | ||||
| func (d *mockDriver) Open(dsn string) (driver.Conn, error) { | ||||
| @@ -39,18 +39,18 @@ func (d *mockDriver) Open(dsn string) (driver.Conn, error) { | ||||
| // and a mock to manage expectations. | ||||
| // Pings db so that all expectations could be | ||||
| // asserted. | ||||
| func New() (db *sql.DB, mock *Sqlmock, err error) { | ||||
| func New() (db *sql.DB, mock Sqlmock, err error) { | ||||
| 	pool.Lock() | ||||
| 	dsn := fmt.Sprintf("sqlmock_db_%d", pool.counter) | ||||
| 	pool.counter++ | ||||
|  | ||||
| 	mock = &Sqlmock{dsn: dsn, drv: pool, MatchExpectationsInOrder: true} | ||||
| 	pool.conns[dsn] = mock | ||||
| 	smock := &sqlmock{dsn: dsn, drv: pool, ordered: true} | ||||
| 	pool.conns[dsn] = smock | ||||
| 	pool.Unlock() | ||||
|  | ||||
| 	db, err = sql.Open("sqlmock", dsn) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return db, mock, db.Ping() | ||||
| 	return db, smock, db.Ping() | ||||
| } | ||||
|   | ||||
| @@ -25,14 +25,15 @@ func TestShouldOpenConnectionIssue15(t *testing.T) { | ||||
| 		t.Errorf("expected 1 connection in pool, but there is: %d", len(pool.conns)) | ||||
| 	} | ||||
|  | ||||
| 	if mock.opened != 1 { | ||||
| 		t.Errorf("expected 1 connection on mock to be opened, but there is: %d", mock.opened) | ||||
| 	smock, _ := mock.(*sqlmock) | ||||
| 	if smock.opened != 1 { | ||||
| 		t.Errorf("expected 1 connection on mock to be opened, but there is: %d", smock.opened) | ||||
| 	} | ||||
|  | ||||
| 	// defer so the rows gets closed first | ||||
| 	defer func() { | ||||
| 		if mock.opened != 0 { | ||||
| 			t.Errorf("expected no connections on mock to be opened, but there is: %d", mock.opened) | ||||
| 		if smock.opened != 0 { | ||||
| 			t.Errorf("expected no connections on mock to be opened, but there is: %d", smock.opened) | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| @@ -49,8 +50,8 @@ func TestShouldOpenConnectionIssue15(t *testing.T) { | ||||
| 	} | ||||
|  | ||||
| 	// now there should be two connections open | ||||
| 	if mock.opened != 2 { | ||||
| 		t.Errorf("expected 2 connection on mock to be opened, but there is: %d", mock.opened) | ||||
| 	if smock.opened != 2 { | ||||
| 		t.Errorf("expected 2 connection on mock to be opened, but there is: %d", smock.opened) | ||||
| 	} | ||||
|  | ||||
| 	mock.ExpectClose() | ||||
| @@ -59,8 +60,8 @@ func TestShouldOpenConnectionIssue15(t *testing.T) { | ||||
| 	} | ||||
|  | ||||
| 	// one is still reserved for rows | ||||
| 	if mock.opened != 1 { | ||||
| 		t.Errorf("expected 1 connection on mock to be still reserved for rows, but there is: %d", mock.opened) | ||||
| 	if smock.opened != 1 { | ||||
| 		t.Errorf("expected 1 connection on mock to be still reserved for rows, but there is: %d", smock.opened) | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -247,7 +247,7 @@ func (e *ExpectedExec) WillReturnResult(result driver.Result) *ExpectedExec { | ||||
| // Returned by *Sqlmock.ExpectPrepare. | ||||
| type ExpectedPrepare struct { | ||||
| 	commonExpectation | ||||
| 	mock      *Sqlmock | ||||
| 	mock      *sqlmock | ||||
| 	sqlRegex  *regexp.Regexp | ||||
| 	statement driver.Stmt | ||||
| 	closeErr  error | ||||
|   | ||||
| @@ -6,7 +6,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| // used for examples | ||||
| var mock = &Sqlmock{} | ||||
| var mock = &sqlmock{} | ||||
|  | ||||
| func ExampleNewErrorResult() { | ||||
| 	db, mock, _ := New() | ||||
|   | ||||
							
								
								
									
										128
									
								
								sqlmock.go
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								sqlmock.go
									
									
									
									
									
								
							| @@ -18,11 +18,48 @@ import ( | ||||
| 	"regexp" | ||||
| ) | ||||
|  | ||||
| // Sqlmock type satisfies required sql.driver interfaces | ||||
| // to simulate actual database and also serves to | ||||
| // create expectations for any kind of database action | ||||
| // in order to mock and test real database behavior. | ||||
| type Sqlmock struct { | ||||
| // Sqlmock interface serves to create expectations | ||||
| // for any kind of database action in order to mock | ||||
| // and test real database behavior. | ||||
| type Sqlmock interface { | ||||
|  | ||||
| 	// ExpectClose queues an expectation for this database | ||||
| 	// action to be triggered. the *ExpectedClose allows | ||||
| 	// to mock database response | ||||
| 	ExpectClose() *ExpectedClose | ||||
|  | ||||
| 	// ExpectationsWereMet checks whether all queued expectations | ||||
| 	// were met in order. If any of them was not met - an error is returned. | ||||
| 	ExpectationsWereMet() error | ||||
|  | ||||
| 	// ExpectPrepare expects Prepare() to be called with sql query | ||||
| 	// which match sqlRegexStr given regexp. | ||||
| 	// the *ExpectedPrepare allows to mock database response. | ||||
| 	// Note that you may expect Query() or Exec() on the *ExpectedPrepare | ||||
| 	// statement to prevent repeating sqlRegexStr | ||||
| 	ExpectPrepare(sqlRegexStr string) *ExpectedPrepare | ||||
|  | ||||
| 	// ExpectQuery expects Query() or QueryRow() to be called with sql query | ||||
| 	// which match sqlRegexStr given regexp. | ||||
| 	// the *ExpectedQuery allows to mock database response. | ||||
| 	ExpectQuery(sqlRegexStr string) *ExpectedQuery | ||||
|  | ||||
| 	// ExpectExec expects Exec() to be called with sql query | ||||
| 	// which match sqlRegexStr given regexp. | ||||
| 	// the *ExpectedExec allows to mock database response | ||||
| 	ExpectExec(sqlRegexStr string) *ExpectedExec | ||||
|  | ||||
| 	// ExpectBegin expects *sql.DB.Begin to be called. | ||||
| 	// the *ExpectedBegin allows to mock database response | ||||
| 	ExpectBegin() *ExpectedBegin | ||||
|  | ||||
| 	// ExpectCommit expects *sql.Tx.Commit to be called. | ||||
| 	// the *ExpectedCommit allows to mock database response | ||||
| 	ExpectCommit() *ExpectedCommit | ||||
|  | ||||
| 	// ExpectRollback expects *sql.Tx.Rollback to be called. | ||||
| 	// the *ExpectedRollback allows to mock database response | ||||
| 	ExpectRollback() *ExpectedRollback | ||||
|  | ||||
| 	// MatchExpectationsInOrder gives an option whether to match all | ||||
| 	// expectations in the order they were set or not. | ||||
| @@ -30,29 +67,33 @@ type Sqlmock struct { | ||||
| 	// By default it is set to - true. But if you use goroutines | ||||
| 	// to parallelize your query executation, that option may | ||||
| 	// be handy. | ||||
| 	MatchExpectationsInOrder bool | ||||
| 	MatchExpectationsInOrder(bool) | ||||
| } | ||||
|  | ||||
| 	dsn    string | ||||
| 	opened int | ||||
| 	drv    *mockDriver | ||||
| type sqlmock struct { | ||||
| 	ordered bool | ||||
| 	dsn     string | ||||
| 	opened  int | ||||
| 	drv     *mockDriver | ||||
|  | ||||
| 	expected []expectation | ||||
| } | ||||
|  | ||||
| // ExpectClose queues an expectation for this database | ||||
| // action to be triggered. the *ExpectedClose allows | ||||
| // to mock database response | ||||
| func (c *Sqlmock) ExpectClose() *ExpectedClose { | ||||
| func (c *sqlmock) ExpectClose() *ExpectedClose { | ||||
| 	e := &ExpectedClose{} | ||||
| 	c.expected = append(c.expected, e) | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| func (c *sqlmock) MatchExpectationsInOrder(b bool) { | ||||
| 	c.ordered = b | ||||
| } | ||||
|  | ||||
| // Close a mock database driver connection. It may or may not | ||||
| // be called depending on the sircumstances, but if it is called | ||||
| // there must be an *ExpectedClose expectation satisfied. | ||||
| // meets http://golang.org/pkg/database/sql/driver/#Conn interface | ||||
| func (c *Sqlmock) Close() error { | ||||
| func (c *sqlmock) Close() error { | ||||
| 	c.drv.Lock() | ||||
| 	defer c.drv.Unlock() | ||||
|  | ||||
| @@ -77,7 +118,7 @@ func (c *Sqlmock) Close() error { | ||||
| 		} | ||||
|  | ||||
| 		next.Unlock() | ||||
| 		if c.MatchExpectationsInOrder { | ||||
| 		if c.ordered { | ||||
| 			return fmt.Errorf("call to database Close, was not expected, next expectation is: %s", next) | ||||
| 		} | ||||
| 	} | ||||
| @@ -95,9 +136,7 @@ func (c *Sqlmock) Close() error { | ||||
| 	return expected.err | ||||
| } | ||||
|  | ||||
| // ExpectationsWereMet checks whether all queued expectations | ||||
| // were met in order. If any of them was not met - an error is returned. | ||||
| func (c *Sqlmock) ExpectationsWereMet() error { | ||||
| func (c *sqlmock) ExpectationsWereMet() error { | ||||
| 	for _, e := range c.expected { | ||||
| 		if !e.fulfilled() { | ||||
| 			return fmt.Errorf("there is a remaining expectation which was not matched: %s", e) | ||||
| @@ -107,7 +146,7 @@ func (c *Sqlmock) ExpectationsWereMet() error { | ||||
| } | ||||
|  | ||||
| // Begin meets http://golang.org/pkg/database/sql/driver/#Conn interface | ||||
| func (c *Sqlmock) Begin() (driver.Tx, error) { | ||||
| func (c *sqlmock) Begin() (driver.Tx, error) { | ||||
| 	var expected *ExpectedBegin | ||||
| 	var ok bool | ||||
| 	var fulfilled int | ||||
| @@ -124,7 +163,7 @@ func (c *Sqlmock) Begin() (driver.Tx, error) { | ||||
| 		} | ||||
|  | ||||
| 		next.Unlock() | ||||
| 		if c.MatchExpectationsInOrder { | ||||
| 		if c.ordered { | ||||
| 			return nil, fmt.Errorf("call to database transaction Begin, was not expected, next expectation is: %s", next) | ||||
| 		} | ||||
| 	} | ||||
| @@ -141,16 +180,14 @@ func (c *Sqlmock) Begin() (driver.Tx, error) { | ||||
| 	return c, expected.err | ||||
| } | ||||
|  | ||||
| // ExpectBegin expects *sql.DB.Begin to be called. | ||||
| // the *ExpectedBegin allows to mock database response | ||||
| func (c *Sqlmock) ExpectBegin() *ExpectedBegin { | ||||
| func (c *sqlmock) ExpectBegin() *ExpectedBegin { | ||||
| 	e := &ExpectedBegin{} | ||||
| 	c.expected = append(c.expected, e) | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| // Exec meets http://golang.org/pkg/database/sql/driver/#Execer | ||||
| func (c *Sqlmock) Exec(query string, args []driver.Value) (res driver.Result, err error) { | ||||
| func (c *sqlmock) Exec(query string, args []driver.Value) (res driver.Result, err error) { | ||||
| 	query = stripQuery(query) | ||||
| 	var expected *ExpectedExec | ||||
| 	var fulfilled int | ||||
| @@ -163,7 +200,7 @@ func (c *Sqlmock) Exec(query string, args []driver.Value) (res driver.Result, er | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if c.MatchExpectationsInOrder { | ||||
| 		if c.ordered { | ||||
| 			if expected, ok = next.(*ExpectedExec); ok { | ||||
| 				break | ||||
| 			} | ||||
| @@ -218,10 +255,7 @@ func (c *Sqlmock) Exec(query string, args []driver.Value) (res driver.Result, er | ||||
| 	return expected.result, err | ||||
| } | ||||
|  | ||||
| // ExpectExec expects Exec() to be called with sql query | ||||
| // which match sqlRegexStr given regexp. | ||||
| // the *ExpectedExec allows to mock database response | ||||
| func (c *Sqlmock) ExpectExec(sqlRegexStr string) *ExpectedExec { | ||||
| func (c *sqlmock) ExpectExec(sqlRegexStr string) *ExpectedExec { | ||||
| 	e := &ExpectedExec{} | ||||
| 	e.sqlRegex = regexp.MustCompile(sqlRegexStr) | ||||
| 	c.expected = append(c.expected, e) | ||||
| @@ -229,7 +263,7 @@ func (c *Sqlmock) ExpectExec(sqlRegexStr string) *ExpectedExec { | ||||
| } | ||||
|  | ||||
| // Prepare meets http://golang.org/pkg/database/sql/driver/#Conn interface | ||||
| func (c *Sqlmock) Prepare(query string) (driver.Stmt, error) { | ||||
| func (c *sqlmock) Prepare(query string) (driver.Stmt, error) { | ||||
| 	var expected *ExpectedPrepare | ||||
| 	var fulfilled int | ||||
| 	var ok bool | ||||
| @@ -246,7 +280,7 @@ func (c *Sqlmock) Prepare(query string) (driver.Stmt, error) { | ||||
| 		} | ||||
|  | ||||
| 		next.Unlock() | ||||
| 		if c.MatchExpectationsInOrder { | ||||
| 		if c.ordered { | ||||
| 			return nil, fmt.Errorf("call to Prepare stetement with query '%s', was not expected, next expectation is: %s", query, next) | ||||
| 		} | ||||
| 	} | ||||
| @@ -265,19 +299,14 @@ func (c *Sqlmock) Prepare(query string) (driver.Stmt, error) { | ||||
| 	return &statement{c, query, expected.closeErr}, expected.err | ||||
| } | ||||
|  | ||||
| // ExpectPrepare expects Prepare() to be called with sql query | ||||
| // which match sqlRegexStr given regexp. | ||||
| // the *ExpectedPrepare allows to mock database response. | ||||
| // Note that you may expect Query() or Exec() on the *ExpectedPrepare | ||||
| // statement to prevent repeating sqlRegexStr | ||||
| func (c *Sqlmock) ExpectPrepare(sqlRegexStr string) *ExpectedPrepare { | ||||
| func (c *sqlmock) ExpectPrepare(sqlRegexStr string) *ExpectedPrepare { | ||||
| 	e := &ExpectedPrepare{sqlRegex: regexp.MustCompile(sqlRegexStr), mock: c} | ||||
| 	c.expected = append(c.expected, e) | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| // Query meets http://golang.org/pkg/database/sql/driver/#Queryer | ||||
| func (c *Sqlmock) Query(query string, args []driver.Value) (rw driver.Rows, err error) { | ||||
| func (c *sqlmock) Query(query string, args []driver.Value) (rw driver.Rows, err error) { | ||||
| 	query = stripQuery(query) | ||||
| 	var expected *ExpectedQuery | ||||
| 	var fulfilled int | ||||
| @@ -290,7 +319,7 @@ func (c *Sqlmock) Query(query string, args []driver.Value) (rw driver.Rows, err | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if c.MatchExpectationsInOrder { | ||||
| 		if c.ordered { | ||||
| 			if expected, ok = next.(*ExpectedQuery); ok { | ||||
| 				break | ||||
| 			} | ||||
| @@ -347,34 +376,27 @@ func (c *Sqlmock) Query(query string, args []driver.Value) (rw driver.Rows, err | ||||
| 	return expected.rows, err | ||||
| } | ||||
|  | ||||
| // ExpectQuery expects Query() or QueryRow() to be called with sql query | ||||
| // which match sqlRegexStr given regexp. | ||||
| // the *ExpectedQuery allows to mock database response. | ||||
| func (c *Sqlmock) ExpectQuery(sqlRegexStr string) *ExpectedQuery { | ||||
| func (c *sqlmock) ExpectQuery(sqlRegexStr string) *ExpectedQuery { | ||||
| 	e := &ExpectedQuery{} | ||||
| 	e.sqlRegex = regexp.MustCompile(sqlRegexStr) | ||||
| 	c.expected = append(c.expected, e) | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| // ExpectCommit expects *sql.Tx.Commit to be called. | ||||
| // the *ExpectedCommit allows to mock database response | ||||
| func (c *Sqlmock) ExpectCommit() *ExpectedCommit { | ||||
| func (c *sqlmock) ExpectCommit() *ExpectedCommit { | ||||
| 	e := &ExpectedCommit{} | ||||
| 	c.expected = append(c.expected, e) | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| // ExpectRollback expects *sql.Tx.Rollback to be called. | ||||
| // the *ExpectedRollback allows to mock database response | ||||
| func (c *Sqlmock) ExpectRollback() *ExpectedRollback { | ||||
| func (c *sqlmock) ExpectRollback() *ExpectedRollback { | ||||
| 	e := &ExpectedRollback{} | ||||
| 	c.expected = append(c.expected, e) | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| // Commit meets http://golang.org/pkg/database/sql/driver/#Tx | ||||
| func (c *Sqlmock) Commit() error { | ||||
| func (c *sqlmock) Commit() error { | ||||
| 	var expected *ExpectedCommit | ||||
| 	var fulfilled int | ||||
| 	var ok bool | ||||
| @@ -391,7 +413,7 @@ func (c *Sqlmock) Commit() error { | ||||
| 		} | ||||
|  | ||||
| 		next.Unlock() | ||||
| 		if c.MatchExpectationsInOrder { | ||||
| 		if c.ordered { | ||||
| 			return fmt.Errorf("call to commit transaction, was not expected, next expectation is: %s", next) | ||||
| 		} | ||||
| 	} | ||||
| @@ -409,7 +431,7 @@ func (c *Sqlmock) Commit() error { | ||||
| } | ||||
|  | ||||
| // Rollback meets http://golang.org/pkg/database/sql/driver/#Tx | ||||
| func (c *Sqlmock) Rollback() error { | ||||
| func (c *sqlmock) Rollback() error { | ||||
| 	var expected *ExpectedRollback | ||||
| 	var fulfilled int | ||||
| 	var ok bool | ||||
| @@ -426,7 +448,7 @@ func (c *Sqlmock) Rollback() error { | ||||
| 		} | ||||
|  | ||||
| 		next.Unlock() | ||||
| 		if c.MatchExpectationsInOrder { | ||||
| 		if c.ordered { | ||||
| 			return fmt.Errorf("call to rollback transaction, was not expected, next expectation is: %s", next) | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -586,7 +586,7 @@ func TestGoroutineExecutionWithUnorderedExpectationMatching(t *testing.T) { | ||||
| 	defer db.Close() | ||||
|  | ||||
| 	// note this line is important for unordered expectation matching | ||||
| 	mock.MatchExpectationsInOrder = false | ||||
| 	mock.MatchExpectationsInOrder(false) | ||||
|  | ||||
| 	result := NewResult(1, 1) | ||||
|  | ||||
| @@ -626,7 +626,7 @@ func ExampleSqlmock_goroutines() { | ||||
| 	defer db.Close() | ||||
|  | ||||
| 	// note this line is important for unordered expectation matching | ||||
| 	mock.MatchExpectationsInOrder = false | ||||
| 	mock.MatchExpectationsInOrder(false) | ||||
|  | ||||
| 	result := NewResult(1, 1) | ||||
|  | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| type statement struct { | ||||
| 	conn  *Sqlmock | ||||
| 	conn  *sqlmock | ||||
| 	query string | ||||
| 	err   error | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user