Skip to content
This repository has been archived by the owner on Jun 27, 2023. It is now read-only.

Commit

Permalink
Fix #71 Do + DoAndReturn signature change error msg (#395)
Browse files Browse the repository at this point in the history
Update the error handling for Call.Do and Call.DoAndReturn in the case where
the argument passed does not match expectations.

* panic if the argument is not a function
* panic if the number of input arguments do not match those expected by Call
* panic if the types of the input arguments do not match those expected
by Call

Call.DoAndReturn has additional validations on the return signature

* panic if the number of return arguments do not match those expected by
Call
* panic if the types of return arguments do not match those expected by
Call
  • Loading branch information
cvgw authored Feb 28, 2020
1 parent b48cb66 commit f9b4ad1
Show file tree
Hide file tree
Showing 4 changed files with 1,109 additions and 3 deletions.
34 changes: 32 additions & 2 deletions gomock/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
"reflect"
"strconv"
"strings"

"github.com/golang/mock/gomock/internal/validate"
)

// Call represents an expected call to a mock.
Expand Down Expand Up @@ -105,10 +107,24 @@ func (c *Call) MaxTimes(n int) *Call {
// DoAndReturn declares the action to run when the call is matched.
// The return values from this function are returned by the mocked function.
// It takes an interface{} argument to support n-arity functions.
// If the method signature of f is not compatible with the mocked function a
// panic will be triggered. Both the arguments and return values of f are
// validated.
func (c *Call) DoAndReturn(f interface{}) *Call {
// TODO: Check arity and types here, rather than dying badly elsewhere.
v := reflect.ValueOf(f)

switch v.Kind() {
case reflect.Func:
mt := c.methodType

ft := v.Type()
if err := validate.InputAndOutputSig(ft, mt); err != nil {
panic(fmt.Sprintf("DoAndReturn: %s", err))
}
default:
panic("DoAndReturn: argument must be a function")
}

c.addAction(func(args []interface{}) []interface{} {
vargs := make([]reflect.Value, len(args))
ft := v.Type()
Expand All @@ -134,10 +150,24 @@ func (c *Call) DoAndReturn(f interface{}) *Call {
// return values are ignored to retain backward compatibility. To use the
// return values call DoAndReturn.
// It takes an interface{} argument to support n-arity functions.
// If the method signature of f is not compatible with the mocked function a
// panic will be triggered. Only the arguments of f are validated; not the return
// values.
func (c *Call) Do(f interface{}) *Call {
// TODO: Check arity and types here, rather than dying badly elsewhere.
v := reflect.ValueOf(f)

switch v.Kind() {
case reflect.Func:
mt := c.methodType

ft := v.Type()
if err := validate.InputSig(ft, mt); err != nil {
panic(fmt.Sprintf("Do: %s", err))
}
default:
panic("Do: argument must be a function")
}

c.addAction(func(args []interface{}) []interface{} {
vargs := make([]reflect.Value, len(args))
ft := v.Type()
Expand Down
Loading

0 comments on commit f9b4ad1

Please # to comment.