-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathadapter.go
216 lines (174 loc) · 5.92 KB
/
adapter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
package gormexpect
import (
"database/sql"
"database/sql/driver"
"github.com/jinzhu/gorm"
sqlmock "gopkg.in/DATA-DOG/go-sqlmock.v1"
)
var (
db *sql.DB
mock sqlmock.Sqlmock
)
func init() {
var err error
db, mock, err = sqlmock.NewWithDSN("mock_gorm_dsn")
if err != nil {
panic(err.Error())
}
}
// Adapter provides an abstract interface over concrete mock database
// implementations (e.g. go-sqlmock or go-testdb)
type Adapter interface {
ExpectQuery(stmt Stmt) Queryer
ExpectExec(stmt Stmt) Execer
ExpectBegin() TxBeginner
ExpectCommit() TxCommitter
ExpectRollback() TxRollback
AssertExpectations() error
}
// NewSqlmockAdapter returns a mock gorm.DB and an Adapter backed by
// go-sqlmock
func NewSqlmockAdapter(dialect string, args ...interface{}) (*gorm.DB, Adapter, error) {
gormDb, err := gorm.Open("sqlmock", "mock_gorm_dsn")
if err != nil {
return nil, nil, err
}
return gormDb, &SqlmockAdapter{db: db, mocker: mock}, nil
}
// SqlmockAdapter implemenets the Adapter interface using go-sqlmock
// it is the default Adapter
type SqlmockAdapter struct {
db *sql.DB
mocker sqlmock.Sqlmock
}
// ExpectQuery wraps the underlying mock method for setting a query
// expectation. It accepts multiple statements in the event of preloading
func (a *SqlmockAdapter) ExpectQuery(query Stmt) Queryer {
expectation := a.mocker.ExpectQuery(query.sql)
return &SqlmockQueryer{query: expectation}
}
// ExpectExec wraps the underlying mock method for setting a exec
// expectation
func (a *SqlmockAdapter) ExpectExec(exec Stmt) Execer {
expectation := a.mocker.ExpectExec(exec.sql)
return &SqlmockExecer{exec: expectation}
}
// ExpectBegin mocks a sql transaction
func (a *SqlmockAdapter) ExpectBegin() TxBeginner {
expectation := a.mocker.ExpectBegin()
return &SqlmockTxBeginner{begin: expectation}
}
// ExpectCommit mocks committing a sql transaction
func (a *SqlmockAdapter) ExpectCommit() TxCommitter {
expectation := a.mocker.ExpectCommit()
return &SqlmockTxCommitter{commit: expectation}
}
// ExpectRollback mocks rolling back a sql
func (a *SqlmockAdapter) ExpectRollback() TxRollback {
expectation := a.mocker.ExpectRollback()
return &SqlmockTxRollback{rollback: expectation}
}
// AssertExpectations asserts that _all_ expectations for a test have been met
// and returns an error specifying which have not if there are unmet
// expectations
func (a *SqlmockAdapter) AssertExpectations() error {
return a.mocker.ExpectationsWereMet()
}
// Queryer is returned from ExpectQuery
// it is used to control the mock database's response
type Queryer interface {
Returns(rows interface{}) Queryer
Errors(err error) Queryer
Args(args ...driver.Value) Queryer
}
// SqlmockQueryer implements Queryer
type SqlmockQueryer struct {
query *sqlmock.ExpectedQuery
}
// Returns will set the low level rows to be returned for a given set of
// queries
func (r *SqlmockQueryer) Returns(rows interface{}) Queryer {
sqlmockRows, ok := rows.(*sqlmock.Rows)
if !ok {
panic("Unsupported type passed to Returns")
}
expectation := r.query.WillReturnRows(sqlmockRows)
return &SqlmockQueryer{query: expectation}
}
// Errors will return an error as the query result
func (r *SqlmockQueryer) Errors(err error) Queryer {
expectation := r.query.WillReturnError(err)
return &SqlmockQueryer{query: expectation}
}
// Args sets the args that queries should be executed with
func (r *SqlmockQueryer) Args(args ...driver.Value) Queryer {
expectation := r.query.WithArgs(args...)
return &SqlmockQueryer{query: expectation}
}
// Execer is a high-level interface to the underlying mock db
type Execer interface {
WillSucceed(lastInsertID, rowsAffected int64) Execer
WillFail(err error) Execer
Args(args ...driver.Value) Execer
}
// SqlmockExecer implements Execer with gosqlmock
type SqlmockExecer struct {
exec *sqlmock.ExpectedExec
}
// WillSucceed accepts a two int64s. They are passed directly to the underlying
// mock db. Useful for checking DAO behaviour in the event that the incorrect
// number of rows are affected by an Exec
func (e *SqlmockExecer) WillSucceed(lastReturnedID, rowsAffected int64) Execer {
result := sqlmock.NewResult(lastReturnedID, rowsAffected)
expectation := e.exec.WillReturnResult(result)
return &SqlmockExecer{exec: expectation}
}
// WillFail simulates returning an Error from an unsuccessful exec
func (e *SqlmockExecer) WillFail(err error) Execer {
expectation := e.exec.WillReturnError(err)
return &SqlmockExecer{exec: expectation}
}
// Args sets the args that the statement should be executed with
func (e *SqlmockExecer) Args(args ...driver.Value) Execer {
expectation := e.exec.WithArgs(args...)
return &SqlmockExecer{exec: expectation}
}
// TxBeginner is an interface to underlying sql.Driver mock implementation
type TxBeginner interface {
WillFail(err error) TxBeginner
}
// SqlmockTxBeginner implements TxBeginner
type SqlmockTxBeginner struct {
begin *sqlmock.ExpectedBegin
}
// WillFail implements TxBeginner
func (b *SqlmockTxBeginner) WillFail(err error) TxBeginner {
expectation := b.begin.WillReturnError(err)
return &SqlmockTxBeginner{begin: expectation}
}
// TxRollback is an interface to underlying mock implementation's tx.Rollback
type TxRollback interface {
WillFail(err error) TxRollback
}
// SqlmockTxCloser implement TxCloser
type SqlmockTxRollback struct {
rollback *sqlmock.ExpectedRollback
}
// WillFail implements TxCloser
func (c *SqlmockTxRollback) WillFail(err error) TxRollback {
expectation := c.rollback.WillReturnError(err)
return &SqlmockTxRollback{rollback: expectation}
}
// TxCommitter is an interface to underlying mock implementation's tx.Commit
type TxCommitter interface {
WillFail(err error) TxCommitter
}
// SqlmockTxCommitter implements TxCommitter
type SqlmockTxCommitter struct {
commit *sqlmock.ExpectedCommit
}
// WillFail implements TxCommitter
func (c *SqlmockTxCommitter) WillFail(err error) TxCommitter {
expectation := c.commit.WillReturnError(err)
return &SqlmockTxCommitter{commit: expectation}
}