stmt_test.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. package sqlx
  2. import (
  3. "database/sql"
  4. "errors"
  5. "testing"
  6. "time"
  7. "github.com/stretchr/testify/assert"
  8. )
  9. var errMockedPlaceholder = errors.New("placeholder")
  10. func TestStmt_exec(t *testing.T) {
  11. tests := []struct {
  12. name string
  13. query string
  14. args []interface{}
  15. delay bool
  16. hasError bool
  17. err error
  18. lastInsertId int64
  19. rowsAffected int64
  20. }{
  21. {
  22. name: "normal",
  23. query: "select user from users where id=?",
  24. args: []interface{}{1},
  25. lastInsertId: 1,
  26. rowsAffected: 2,
  27. },
  28. {
  29. name: "exec error",
  30. query: "select user from users where id=?",
  31. args: []interface{}{1},
  32. hasError: true,
  33. err: errors.New("exec"),
  34. },
  35. {
  36. name: "exec more args error",
  37. query: "select user from users where id=? and name=?",
  38. args: []interface{}{1},
  39. hasError: true,
  40. err: errors.New("exec"),
  41. },
  42. {
  43. name: "slowcall",
  44. query: "select user from users where id=?",
  45. args: []interface{}{1},
  46. delay: true,
  47. lastInsertId: 1,
  48. rowsAffected: 2,
  49. },
  50. }
  51. for _, test := range tests {
  52. test := test
  53. fns := []func(args ...interface{}) (sql.Result, error){
  54. func(args ...interface{}) (sql.Result, error) {
  55. return exec(&mockedSessionConn{
  56. lastInsertId: test.lastInsertId,
  57. rowsAffected: test.rowsAffected,
  58. err: test.err,
  59. delay: test.delay,
  60. }, test.query, args...)
  61. },
  62. func(args ...interface{}) (sql.Result, error) {
  63. return execStmt(&mockedStmtConn{
  64. lastInsertId: test.lastInsertId,
  65. rowsAffected: test.rowsAffected,
  66. err: test.err,
  67. delay: test.delay,
  68. }, test.query, args...)
  69. },
  70. }
  71. for _, fn := range fns {
  72. fn := fn
  73. t.Run(test.name, func(t *testing.T) {
  74. t.Parallel()
  75. res, err := fn(test.args...)
  76. if test.hasError {
  77. assert.NotNil(t, err)
  78. return
  79. }
  80. assert.Nil(t, err)
  81. lastInsertId, err := res.LastInsertId()
  82. assert.Nil(t, err)
  83. assert.Equal(t, test.lastInsertId, lastInsertId)
  84. rowsAffected, err := res.RowsAffected()
  85. assert.Nil(t, err)
  86. assert.Equal(t, test.rowsAffected, rowsAffected)
  87. })
  88. }
  89. }
  90. }
  91. func TestStmt_query(t *testing.T) {
  92. tests := []struct {
  93. name string
  94. query string
  95. args []interface{}
  96. delay bool
  97. hasError bool
  98. err error
  99. }{
  100. {
  101. name: "normal",
  102. query: "select user from users where id=?",
  103. args: []interface{}{1},
  104. },
  105. {
  106. name: "query error",
  107. query: "select user from users where id=?",
  108. args: []interface{}{1},
  109. hasError: true,
  110. err: errors.New("exec"),
  111. },
  112. {
  113. name: "query more args error",
  114. query: "select user from users where id=? and name=?",
  115. args: []interface{}{1},
  116. hasError: true,
  117. err: errors.New("exec"),
  118. },
  119. {
  120. name: "slowcall",
  121. query: "select user from users where id=?",
  122. args: []interface{}{1},
  123. delay: true,
  124. },
  125. }
  126. for _, test := range tests {
  127. test := test
  128. fns := []func(args ...interface{}) error{
  129. func(args ...interface{}) error {
  130. return query(&mockedSessionConn{
  131. err: test.err,
  132. delay: test.delay,
  133. }, func(rows *sql.Rows) error {
  134. return nil
  135. }, test.query, args...)
  136. },
  137. func(args ...interface{}) error {
  138. return queryStmt(&mockedStmtConn{
  139. err: test.err,
  140. delay: test.delay,
  141. }, func(rows *sql.Rows) error {
  142. return nil
  143. }, test.query, args...)
  144. },
  145. }
  146. for _, fn := range fns {
  147. fn := fn
  148. t.Run(test.name, func(t *testing.T) {
  149. t.Parallel()
  150. err := fn(test.args...)
  151. if test.hasError {
  152. assert.NotNil(t, err)
  153. return
  154. }
  155. assert.NotNil(t, err)
  156. })
  157. }
  158. }
  159. }
  160. type mockedSessionConn struct {
  161. lastInsertId int64
  162. rowsAffected int64
  163. err error
  164. delay bool
  165. }
  166. func (m *mockedSessionConn) Exec(query string, args ...interface{}) (sql.Result, error) {
  167. if m.delay {
  168. time.Sleep(slowThreshold + time.Millisecond)
  169. }
  170. return mockedResult{
  171. lastInsertId: m.lastInsertId,
  172. rowsAffected: m.rowsAffected,
  173. }, m.err
  174. }
  175. func (m *mockedSessionConn) Query(query string, args ...interface{}) (*sql.Rows, error) {
  176. if m.delay {
  177. time.Sleep(slowThreshold + time.Millisecond)
  178. }
  179. err := errMockedPlaceholder
  180. if m.err != nil {
  181. err = m.err
  182. }
  183. return new(sql.Rows), err
  184. }
  185. type mockedStmtConn struct {
  186. lastInsertId int64
  187. rowsAffected int64
  188. err error
  189. delay bool
  190. }
  191. func (m *mockedStmtConn) Exec(args ...interface{}) (sql.Result, error) {
  192. if m.delay {
  193. time.Sleep(slowThreshold + time.Millisecond)
  194. }
  195. return mockedResult{
  196. lastInsertId: m.lastInsertId,
  197. rowsAffected: m.rowsAffected,
  198. }, m.err
  199. }
  200. func (m *mockedStmtConn) Query(args ...interface{}) (*sql.Rows, error) {
  201. if m.delay {
  202. time.Sleep(slowThreshold + time.Millisecond)
  203. }
  204. err := errMockedPlaceholder
  205. if m.err != nil {
  206. err = m.err
  207. }
  208. return new(sql.Rows), err
  209. }
  210. type mockedResult struct {
  211. lastInsertId int64
  212. rowsAffected int64
  213. }
  214. func (m mockedResult) LastInsertId() (int64, error) {
  215. return m.lastInsertId, nil
  216. }
  217. func (m mockedResult) RowsAffected() (int64, error) {
  218. return m.rowsAffected, nil
  219. }