@@ -25,12 +25,11 @@ import (
25
25
type Call struct {
26
26
t TestReporter // for triggering test failures on invalid call setup
27
27
28
- receiver interface {} // the receiver of the method call
29
- method string // the name of the method
30
- methodType reflect.Type // the type of the method
31
- args []Matcher // the args
32
- rets []interface {} // the return values (if any)
33
- origin string // file and line number of call setup
28
+ receiver interface {} // the receiver of the method call
29
+ method string // the name of the method
30
+ methodType reflect.Type // the type of the method
31
+ args []Matcher // the args
32
+ origin string // file and line number of call setup
34
33
35
34
preReqs []* Call // prerequisite calls
36
35
@@ -39,9 +38,10 @@ type Call struct {
39
38
40
39
numCalls int // actual number made
41
40
42
- // Actions
43
- doFunc reflect.Value
44
- setArgs map [int ]reflect.Value
41
+ // actions are called when this Call is called. Each action gets the args and
42
+ // can set the return values by returning a non-nil slice. Actions run in the
43
+ // order they are created.
44
+ actions []func ([]interface {}) []interface {}
45
45
}
46
46
47
47
// AnyTimes allows the expectation to be called 0 or more times
@@ -70,11 +70,56 @@ func (c *Call) MaxTimes(n int) *Call {
70
70
return c
71
71
}
72
72
73
- // Do declares the action to run when the call is matched.
73
+ // DoAndReturn declares the action to run when the call is matched.
74
+ // The return values from this function are returned by the mocked function.
75
+ // It takes an interface{} argument to support n-arity functions.
76
+ func (c * Call ) DoAndReturn (f interface {}) * Call {
77
+ // TODO: Check arity and types here, rather than dying badly elsewhere.
78
+ v := reflect .ValueOf (f )
79
+
80
+ c .addAction (func (args []interface {}) []interface {} {
81
+ vargs := make ([]reflect.Value , len (args ))
82
+ ft := v .Type ()
83
+ for i := 0 ; i < len (args ); i ++ {
84
+ if args [i ] != nil {
85
+ vargs [i ] = reflect .ValueOf (args [i ])
86
+ } else {
87
+ // Use the zero value for the arg.
88
+ vargs [i ] = reflect .Zero (ft .In (i ))
89
+ }
90
+ }
91
+ vrets := v .Call (vargs )
92
+ rets := make ([]interface {}, len (vrets ))
93
+ for i , ret := range vrets {
94
+ rets [i ] = ret .Interface ()
95
+ }
96
+ return rets
97
+ })
98
+ return c
99
+ }
100
+
101
+ // Do declares the action to run when the call is matched. The function's
102
+ // return values are ignored to retain backward compatibility. To use the
103
+ // return values call DoAndReturn.
74
104
// It takes an interface{} argument to support n-arity functions.
75
105
func (c * Call ) Do (f interface {}) * Call {
76
106
// TODO: Check arity and types here, rather than dying badly elsewhere.
77
- c .doFunc = reflect .ValueOf (f )
107
+ v := reflect .ValueOf (f )
108
+
109
+ c .addAction (func (args []interface {}) []interface {} {
110
+ vargs := make ([]reflect.Value , len (args ))
111
+ ft := v .Type ()
112
+ for i := 0 ; i < len (args ); i ++ {
113
+ if args [i ] != nil {
114
+ vargs [i ] = reflect .ValueOf (args [i ])
115
+ } else {
116
+ // Use the zero value for the arg.
117
+ vargs [i ] = reflect .Zero (ft .In (i ))
118
+ }
119
+ v .Call (vargs )
120
+ }
121
+ return nil
122
+ })
78
123
return c
79
124
}
80
125
@@ -113,7 +158,10 @@ func (c *Call) Return(rets ...interface{}) *Call {
113
158
}
114
159
}
115
160
116
- c .rets = rets
161
+ c .addAction (func ([]interface {}) []interface {} {
162
+ return rets
163
+ })
164
+
117
165
return c
118
166
}
119
167
@@ -131,9 +179,6 @@ func (c *Call) SetArg(n int, value interface{}) *Call {
131
179
h .Helper ()
132
180
}
133
181
134
- if c .setArgs == nil {
135
- c .setArgs = make (map [int ]reflect.Value )
136
- }
137
182
mt := c .methodType
138
183
// TODO: This will break on variadic methods.
139
184
// We will need to check those at invocation time.
@@ -159,7 +204,17 @@ func (c *Call) SetArg(n int, value interface{}) *Call {
159
204
c .t .Fatalf ("SetArg(%d, ...) referring to argument of non-pointer non-interface non-slice type %v [%s]" ,
160
205
n , at , c .origin )
161
206
}
162
- c .setArgs [n ] = reflect .ValueOf (value )
207
+
208
+ c .addAction (func (args []interface {}) []interface {} {
209
+ v := reflect .ValueOf (value )
210
+ switch reflect .TypeOf (args [n ]).Kind () {
211
+ case reflect .Slice :
212
+ setSlice (args [n ], v )
213
+ default :
214
+ reflect .ValueOf (args [n ]).Elem ().Set (v )
215
+ }
216
+ return nil
217
+ })
163
218
return c
164
219
}
165
220
@@ -296,43 +351,21 @@ func (c *Call) dropPrereqs() (preReqs []*Call) {
296
351
return
297
352
}
298
353
299
- func (c * Call ) call (args []interface {}) (rets []interface {}, action func ()) {
300
- c .numCalls ++
301
-
302
- // Actions
303
- if c .doFunc .IsValid () {
304
- doArgs := make ([]reflect.Value , len (args ))
305
- ft := c .doFunc .Type ()
306
- for i := 0 ; i < len (args ); i ++ {
307
- if args [i ] != nil {
308
- doArgs [i ] = reflect .ValueOf (args [i ])
309
- } else {
310
- // Use the zero value for the arg.
311
- doArgs [i ] = reflect .Zero (ft .In (i ))
312
- }
313
- }
314
- action = func () { c .doFunc .Call (doArgs ) }
315
- }
316
- for n , v := range c .setArgs {
317
- switch reflect .TypeOf (args [n ]).Kind () {
318
- case reflect .Slice :
319
- setSlice (args [n ], v )
320
- default :
321
- reflect .ValueOf (args [n ]).Elem ().Set (v )
322
- }
323
- }
324
-
325
- rets = c .rets
326
- if rets == nil {
354
+ func (c * Call ) defaultActions () []func ([]interface {}) []interface {} {
355
+ return []func ([]interface {}) []interface {}{func ([]interface {}) []interface {} {
327
356
// Synthesize the zero value for each of the return args' types.
328
357
mt := c .methodType
329
- rets = make ([]interface {}, mt .NumOut ())
358
+ rets : = make ([]interface {}, mt .NumOut ())
330
359
for i := 0 ; i < mt .NumOut (); i ++ {
331
360
rets [i ] = reflect .Zero (mt .Out (i )).Interface ()
332
361
}
333
- }
362
+ return rets
363
+ }}
364
+ }
334
365
335
- return
366
+ func (c * Call ) call (args []interface {}) []func ([]interface {}) []interface {} {
367
+ c .numCalls ++
368
+ return c .actions
336
369
}
337
370
338
371
// InOrder declares that the given calls should occur in order.
@@ -348,3 +381,7 @@ func setSlice(arg interface{}, v reflect.Value) {
348
381
va .Index (i ).Set (v .Index (i ))
349
382
}
350
383
}
384
+
385
+ func (c * Call ) addAction (action func ([]interface {}) []interface {}) {
386
+ c .actions = append (c .actions , action )
387
+ }
0 commit comments