-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathassociation.go
161 lines (135 loc) · 4.3 KB
/
association.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
package gormexpect
import (
"fmt"
"github.com/jinzhu/gorm"
)
// Operation represents the Association method being called. Behaviour
// internally changes depending on the operation.
type Operation int
const (
Find Operation = iota
Append
Replace
Delete
Count
Clear
)
// MockAssociation mirros gorm.Association
type MockAssociation struct {
column string
parent *Expecter
noopAssociation *gorm.Association
operation Operation
}
// QueryWrapper is just a wrapper over QueryExpectation. This is necessary to
// allow MockAssociation to have a fluent API
type QueryWrapper struct {
association *MockAssociation
expectation QueryExpectation
}
// Returns functions in the same way as Expecter.Returns
func (w *QueryWrapper) Returns(value interface{}) *MockAssociation {
w.expectation.Returns(value)
return w.association
}
// ExecWrapper wraps ExecExpectation
type ExecWrapper struct {
association *MockAssociation
expectation ExecExpectation
}
// WillSucceed has the same signature as ExecExpectation.WillSucceed. It is
// only returned from Append() and Replace().
func (w *ExecWrapper) WillSucceed(lastReturnID, rowsAffected int64) {
switch w.association.operation {
case Replace:
handleReplace(w.association, true)
case Append, Clear, Delete:
handleAssociationGeneric(w.association)
default:
return
}
}
// NewMockAssociation returns a MockAssociation
func NewMockAssociation(c string, a *gorm.Association, e *Expecter) *MockAssociation {
return &MockAssociation{column: c, parent: e, noopAssociation: a}
}
// Find wraps gorm.Association
func (a *MockAssociation) Find(value interface{}) *QueryWrapper {
a.noopAssociation.Find(&value)
expectation := &SqlmockQueryExpectation{association: a, parent: a.parent}
return &QueryWrapper{association: a, expectation: expectation}
}
// Append wraps gorm.Association.Append
func (a *MockAssociation) Append(values ...interface{}) *ExecWrapper {
a.operation = Append
a.noopAssociation.Append(values...)
expectation := &SqlmockExecExpectation{parent: a.parent}
return &ExecWrapper{association: a, expectation: expectation}
}
// Delete wraps gorm.Association.Delete
func (a *MockAssociation) Delete(values ...interface{}) *ExecWrapper {
a.operation = Delete
a.noopAssociation.Delete(values...)
expectation := &SqlmockExecExpectation{parent: a.parent}
return &ExecWrapper{association: a, expectation: expectation}
}
// Clear wraps gorm.Association.Clear
func (a *MockAssociation) Clear() *ExecWrapper {
a.operation = Replace
a.noopAssociation.Clear()
expectation := &SqlmockExecExpectation{parent: a.parent}
return &ExecWrapper{association: a, expectation: expectation}
}
// Replace wraps gorm.Association.Replace
func (a *MockAssociation) Replace(values ...interface{}) *ExecWrapper {
a.operation = Replace
a.parent.noop.ReturnExecResult(1, 1)
a.noopAssociation.Replace(values...)
expectation := &SqlmockExecExpectation{parent: a.parent}
return &ExecWrapper{association: a, expectation: expectation}
}
// Count wraps gorm.Association.Count
func (a *MockAssociation) Count() *QueryWrapper {
a.noopAssociation.Count()
expectation := &SqlmockQueryExpectation{parent: a.parent}
return &QueryWrapper{association: a, expectation: expectation}
}
func handleAssociationGeneric(association *MockAssociation) {
expecter := association.parent
adapter := association.parent.adapter
value := association.parent.gorm.Value
stmts := association.parent.recorder.stmts
for i, stmt := range stmts {
switch i {
case 0:
adapter.ExpectExec(stmt).WillSucceed(1, 1)
case 1:
newExpecter := expecter.clone()
newExpecter.recorder.stmts = []Stmt{stmt}
newExpecter.Find(&value).Returns(value)
}
}
}
func handleReplace(association *MockAssociation, isSuccessful bool) {
expecter := association.parent
stmts := association.parent.recorder.stmts
adapter := association.parent.adapter
value := association.parent.gorm.Value
for i, stmt := range stmts {
switch i {
// INSERT
case 0:
adapter.ExpectExec(stmt).WillSucceed(1, 1)
// SELECT
case 1:
newExpecter := expecter.clone()
newExpecter.recorder.stmts = []Stmt{stmt}
newExpecter.Find(&value).Returns(value)
// UPDATE
case 2:
adapter.ExpectExec(stmt).WillSucceed(1, 1)
default:
panic(fmt.Sprintf("Replace should not generate more than three SQL statements, got %d", len(stmts)))
}
}
}