Repository: golang/mock (go)

Issue:
gomock fails with unexported interface methods in go 1.7
When working with unexported interface methods, even within the same package, errors are thrown in Go 1.7.

``` go
//bugreport.go
package bugreport

import "fmt"

// Example is an interface with a non exported method
type Example interface {
        someMethod(string) string
}

// CallExample is a simple function that uses the interface
func CallExample(e Example) {
        fmt.Println(e.someMethod("test"))
}
```

``` sh
mockgen -destination  bugreport_mock_test.go -package bugreport -source=bugreport.go Example
```

``` go
//bugreport_test.go
package bugreport

import (
        "testing"

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

func TestCallExample(t *testing.T) {
        ctrl := gomock.NewController(t)
        defer ctrl.Finish()

        e := NewMockExample(ctrl)
        e.EXPECT().someMethod(gomock.Any()).Return("it works!")

        CallExample(e)
}
```

``` sh
go test                                                                                                                                                                                                                                                                                                                                                        !24218
--- FAIL: TestCallExample (0.00s)
panic: gomock: failed finding method someMethod on *bugreport.MockExample [recovered]
        panic: gomock: failed finding method someMethod on *bugreport.MockExample [recovered]
        panic: gomock: failed finding method someMethod on *bugreport.MockExample
```

The same test with someMethod written as SomeMethod works fine and as expected. This same test also works in Go 1.6.


Pull request description:
Fix mocks with unexported methods
As noted in #52, mocks for interfaces with unexported methods stopped working. A solution was proposed in #59 but I didn't like adding another function to the mock so I'm proposing this alternative, heavily inspired by #59. 

The down side is that it changes the interface to gomock.RecordCall. I don't expect anybody other than the recorder to be calling it but somebody out there probably is doing something fancy and calling it directly. This will break them.

Fixes #52 

Patch:
diff --git a/gomock/call.go b/gomock/call.go
index 035aa75..82e9f70 100644
--- a/gomock/call.go
+++ b/gomock/call.go
@@ -24,10 +24,11 @@ import (
 type Call struct {
 	t TestReporter // for triggering test failures on invalid call setup
 
-	receiver interface{}   // the receiver of the method call
-	method   string        // the name of the method
-	args     []Matcher     // the args
-	rets     []interface{} // the return values (if any)
+	receiver   interface{}   // the receiver of the method call
+	method     string        // the name of the method
+	methodType reflect.Type  // the type of the method
+	args       []Matcher     // the args
+	rets       []interface{} // the return values (if any)
 
 	preReqs []*Call // prerequisite calls
 
@@ -76,7 +77,7 @@ func (c *Call) Do(f interface{}) *Call {
 }
 
 func (c *Call) Return(rets ...interface{}) *Call {
-	mt := c.methodType()
+	mt := c.methodType
 	if len(rets) != mt.NumOut() {
 		c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d",
 			c.receiver, c.method, len(rets), mt.NumOut())
@@ -120,7 +121,7 @@ func (c *Call) SetArg(n int, value interface{}) *Call {
 	if c.setArgs == nil {
 		c.setArgs = make(map[int]reflect.Value)
 	}
-	mt := c.methodType()
+	mt := c.methodType
 	// TODO: This will break on variadic methods.
 	// We will need to check those at invocation time.
 	if n < 0 || n >= mt.NumIn() {
@@ -240,7 +241,7 @@ func (c *Call) call(args []interface{}) (rets []interface{}, action func()) {
 	rets = c.rets
 	if rets == nil {
 		// Synthesize the zero value for each of the return args' types.
-		mt := c.methodType()
+		mt := c.methodType
 		rets = make([]interface{}, mt.NumOut())
 		for i := 0; i < mt.NumOut(); i++ {
 			rets[i] = reflect.Zero(mt.Out(i)).Interface()
@@ -250,16 +251,6 @@ func (c *Call) call(args []interface{}) (rets []interface{}, action func()) {
 	return
 }
 
-func (c *Call) methodType() reflect.Type {
-	recv := reflect.ValueOf(c.receiver)
-	for i := 0; i < recv.Type().NumMethod(); i++ {
-		if recv.Type().Method(i).Name == c.method {
-			return recv.Method(i).Type()
-		}
-	}
-	panic(fmt.Sprintf("gomock: failed finding method %s on %T", c.method, c.receiver))
-}
-
 // InOrder declares that the given calls should occur in order.
 func InOrder(calls ...*Call) {
 	for i := 1; i < len(calls); i++ {
diff --git a/gomock/controller.go b/gomock/controller.go
index 6ca9528..3af6424 100644
--- a/gomock/controller.go
+++ b/gomock/controller.go
@@ -55,7 +55,10 @@
 //	- Handle different argument/return types (e.g. ..., chan, map, interface).
 package gomock
 
-import "sync"
+import (
+	"reflect"
+	"sync"
+)
 
 // A TestReporter is something that can be used to report test failures.
 // It is satisfied by the standard library's *testing.T.
@@ -80,7 +83,7 @@ func NewController(t TestReporter) *Controller {
 	}
 }
 
-func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ...interface{}) *Call {
+func (ctrl *Controller) RecordCall(receiver interface{}, method string, methodType reflect.Type, args ...interface{}) *Call {
 	// TODO: check arity, types.
 	margs := make([]Matcher, len(args))
 	for i, arg := range args {
@@ -98,7 +101,7 @@ func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ...
 	ctrl.mu.Lock()
 	defer ctrl.mu.Unlock()
 
-	call := &Call{t: ctrl.t, receiver: receiver, method: method, args: margs, minCalls: 1, maxCalls: 1}
+	call := &Call{t: ctrl.t, receiver: receiver, method: method, methodType: methodType, args: margs, minCalls: 1, maxCalls: 1}
 
 	ctrl.expectedCalls.Add(call)
 	return call
diff --git a/gomock/mock_matcher/mock_matcher.go b/gomock/mock_matcher/mock_matcher.go
index 4220523..af92e88 100644
--- a/gomock/mock_matcher/mock_matcher.go
+++ b/gomock/mock_matcher/mock_matcher.go
@@ -5,6 +5,7 @@ package mock_gomock
 
 import (
 	gomock "github.com/golang/mock/gomock"
+	reflect "reflect"
 )
 
 // MockMatcher is a mock of Matcher interface
@@ -39,7 +40,7 @@ func (_m *MockMatcher) Matches(_param0 interface{}) bool {
 
 // Matches indicates an expected call of Matches
 func (_mr *MockMatcherMockRecorder) Matches(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "Matches", arg0)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Matches", reflect.TypeOf((*MockMatcher)(nil).Matches), arg0)
 }
 
 // String mocks base method
@@ -51,5 +52,5 @@ func (_m *MockMatcher) String() string {
 
 // String indicates an expected call of String
 func (_mr *MockMatcherMockRecorder) String() *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "String")
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "String", reflect.TypeOf((*MockMatcher)(nil).String))
 }
diff --git a/mockgen/mockgen.go b/mockgen/mockgen.go
index a7ad50c..ac6b073 100644
--- a/mockgen/mockgen.go
+++ b/mockgen/mockgen.go
@@ -193,6 +193,7 @@ func (g *generator) Generate(pkg *model.Package, pkgName string) error {
 	// Get all required imports, and generate unique names for them all.
 	im := pkg.Imports()
 	im[gomockImportPath] = true
+	im["reflect"] = true
 
 	// Sort keys to make import alias generation predictable
 	sorted_paths := make([]string, len(im), len(im))
@@ -424,7 +425,7 @@ func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method)
 			callArgs = ", _s..."
 		}
 	}
-	g.p(`return _mr.mock.ctrl.RecordCall(_mr.mock, "%v"%v)`, m.Name, callArgs)
+	g.p(`return _mr.mock.ctrl.RecordCall(_mr.mock, "%s", reflect.TypeOf((*%s)(nil).%s)%s)`, m.Name, mockType, m.Name, callArgs)
 
 	g.out()
 	g.p("}")
diff --git a/sample/mock_user/mock_user.go b/sample/mock_user/mock_user.go
index a354cb5..f518a52 100644
--- a/sample/mock_user/mock_user.go
+++ b/sample/mock_user/mock_user.go
@@ -15,6 +15,7 @@ import (
 	template "html/template"
 	io "io"
 	http "net/http"
+	reflect "reflect"
 	template0 "text/template"
 )
 
@@ -48,7 +49,7 @@ func (_m *MockIndex) Anon(_param0 string) {
 
 // Anon indicates an expected call of Anon
 func (_mr *MockIndexMockRecorder) Anon(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "Anon", arg0)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Anon", reflect.TypeOf((*MockIndex)(nil).Anon), arg0)
 }
 
 // Chan mocks base method
@@ -58,7 +59,7 @@ func (_m *MockIndex) Chan(_param0 chan int, _param1 chan<- hash.Hash) {
 
 // Chan indicates an expected call of Chan
 func (_mr *MockIndexMockRecorder) Chan(arg0, arg1 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "Chan", arg0, arg1)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Chan", reflect.TypeOf((*MockIndex)(nil).Chan), arg0, arg1)
 }
 
 // ConcreteRet mocks base method
@@ -70,7 +71,7 @@ func (_m *MockIndex) ConcreteRet() chan<- bool {
 
 // ConcreteRet indicates an expected call of ConcreteRet
 func (_mr *MockIndexMockRecorder) ConcreteRet() *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "ConcreteRet")
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "ConcreteRet", reflect.TypeOf((*MockIndex)(nil).ConcreteRet))
 }
 
 // Ellip mocks base method
@@ -85,7 +86,7 @@ func (_m *MockIndex) Ellip(_param0 string, _param1 ...interface{}) {
 // Ellip indicates an expected call of Ellip
 func (_mr *MockIndexMockRecorder) Ellip(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
 	_s := append([]interface{}{arg0}, arg1...)
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "Ellip", _s...)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Ellip", reflect.TypeOf((*MockIndex)(nil).Ellip), _s...)
 }
 
 // EllipOnly mocks base method
@@ -99,7 +100,7 @@ func (_m *MockIndex) EllipOnly(_param0 ...string) {
 
 // EllipOnly indicates an expected call of EllipOnly
 func (_mr *MockIndexMockRecorder) EllipOnly(arg0 ...interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "EllipOnly", arg0...)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "EllipOnly", reflect.TypeOf((*MockIndex)(nil).EllipOnly), arg0...)
 }
 
 // ForeignFour mocks base method
@@ -109,7 +110,7 @@ func (_m *MockIndex) ForeignFour(_param0 imp4.Imp4) {
 
 // ForeignFour indicates an expected call of ForeignFour
 func (_mr *MockIndexMockRecorder) ForeignFour(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "ForeignFour", arg0)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "ForeignFour", reflect.TypeOf((*MockIndex)(nil).ForeignFour), arg0)
 }
 
 // ForeignOne mocks base method
@@ -119,7 +120,7 @@ func (_m *MockIndex) ForeignOne(_param0 imp1.Imp1) {
 
 // ForeignOne indicates an expected call of ForeignOne
 func (_mr *MockIndexMockRecorder) ForeignOne(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "ForeignOne", arg0)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "ForeignOne", reflect.TypeOf((*MockIndex)(nil).ForeignOne), arg0)
 }
 
 // ForeignThree mocks base method
@@ -129,7 +130,7 @@ func (_m *MockIndex) ForeignThree(_param0 imp3.Imp3) {
 
 // ForeignThree indicates an expected call of ForeignThree
 func (_mr *MockIndexMockRecorder) ForeignThree(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "ForeignThree", arg0)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "ForeignThree", reflect.TypeOf((*MockIndex)(nil).ForeignThree), arg0)
 }
 
 // ForeignTwo mocks base method
@@ -139,7 +140,7 @@ func (_m *MockIndex) ForeignTwo(_param0 imp2.Imp2) {
 
 // ForeignTwo indicates an expected call of ForeignTwo
 func (_mr *MockIndexMockRecorder) ForeignTwo(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "ForeignTwo", arg0)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "ForeignTwo", reflect.TypeOf((*MockIndex)(nil).ForeignTwo), arg0)
 }
 
 // Func mocks base method
@@ -149,7 +150,7 @@ func (_m *MockIndex) Func(_param0 func(http.Request) (int, bool)) {
 
 // Func indicates an expected call of Func
 func (_mr *MockIndexMockRecorder) Func(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "Func", arg0)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Func", reflect.TypeOf((*MockIndex)(nil).Func), arg0)
 }
 
 // Get mocks base method
@@ -161,7 +162,7 @@ func (_m *MockIndex) Get(_param0 string) interface{} {
 
 // Get indicates an expected call of Get
 func (_mr *MockIndexMockRecorder) Get(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "Get", arg0)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Get", reflect.TypeOf((*MockIndex)(nil).Get), arg0)
 }
 
 // GetTwo mocks base method
@@ -174,7 +175,7 @@ func (_m *MockIndex) GetTwo(_param0 string, _param1 string) (interface{}, interf
 
 // GetTwo indicates an expected call of GetTwo
 func (_mr *MockIndexMockRecorder) GetTwo(arg0, arg1 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "GetTwo", arg0, arg1)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "GetTwo", reflect.TypeOf((*MockIndex)(nil).GetTwo), arg0, arg1)
 }
 
 // Map mocks base method
@@ -184,7 +185,7 @@ func (_m *MockIndex) Map(_param0 map[int]hash.Hash) {
 
 // Map indicates an expected call of Map
 func (_mr *MockIndexMockRecorder) Map(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "Map", arg0)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Map", reflect.TypeOf((*MockIndex)(nil).Map), arg0)
 }
 
 // NillableRet mocks base method
@@ -196,7 +197,7 @@ func (_m *MockIndex) NillableRet() error {
 
 // NillableRet indicates an expected call of NillableRet
 func (_mr *MockIndexMockRecorder) NillableRet() *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "NillableRet")
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "NillableRet", reflect.TypeOf((*MockIndex)(nil).NillableRet))
 }
 
 // Other mocks base method
@@ -208,7 +209,7 @@ func (_m *MockIndex) Other() hash.Hash {
 
 // Other indicates an expected call of Other
 func (_mr *MockIndexMockRecorder) Other() *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "Other")
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Other", reflect.TypeOf((*MockIndex)(nil).Other))
 }
 
 // Ptr mocks base method
@@ -218,7 +219,7 @@ func (_m *MockIndex) Ptr(_param0 *int) {
 
 // Ptr indicates an expected call of Ptr
 func (_mr *MockIndexMockRecorder) Ptr(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "Ptr", arg0)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Ptr", reflect.TypeOf((*MockIndex)(nil).Ptr), arg0)
 }
 
 // Put mocks base method
@@ -228,7 +229,7 @@ func (_m *MockIndex) Put(_param0 string, _param1 interface{}) {
 
 // Put indicates an expected call of Put
 func (_mr *MockIndexMockRecorder) Put(arg0, arg1 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "Put", arg0, arg1)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Put", reflect.TypeOf((*MockIndex)(nil).Put), arg0, arg1)
 }
 
 // Slice mocks base method
@@ -240,7 +241,7 @@ func (_m *MockIndex) Slice(_param0 []int, _param1 []byte) [3]int {
 
 // Slice indicates an expected call of Slice
 func (_mr *MockIndexMockRecorder) Slice(arg0, arg1 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "Slice", arg0, arg1)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Slice", reflect.TypeOf((*MockIndex)(nil).Slice), arg0, arg1)
 }
 
 // Struct mocks base method
@@ -250,7 +251,7 @@ func (_m *MockIndex) Struct(_param0 struct{}) {
 
 // Struct indicates an expected call of Struct
 func (_mr *MockIndexMockRecorder) Struct(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "Struct", arg0)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Struct", reflect.TypeOf((*MockIndex)(nil).Struct), arg0)
 }
 
 // StructChan mocks base method
@@ -260,7 +261,7 @@ func (_m *MockIndex) StructChan(_param0 chan struct{}) {
 
 // StructChan indicates an expected call of StructChan
 func (_mr *MockIndexMockRecorder) StructChan(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "StructChan", arg0)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "StructChan", reflect.TypeOf((*MockIndex)(nil).StructChan), arg0)
 }
 
 // Summary mocks base method
@@ -270,7 +271,7 @@ func (_m *MockIndex) Summary(_param0 *bytes.Buffer, _param1 io.Writer) {
 
 // Summary indicates an expected call of Summary
 func (_mr *MockIndexMockRecorder) Summary(arg0, arg1 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "Summary", arg0, arg1)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Summary", reflect.TypeOf((*MockIndex)(nil).Summary), arg0, arg1)
 }
 
 // Templates mocks base method
@@ -280,7 +281,7 @@ func (_m *MockIndex) Templates(_param0 template.CSS, _param1 template0.FuncMap)
 
 // Templates indicates an expected call of Templates
 func (_mr *MockIndexMockRecorder) Templates(arg0, arg1 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "Templates", arg0, arg1)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "Templates", reflect.TypeOf((*MockIndex)(nil).Templates), arg0, arg1)
 }
 
 // MockEmbed is a mock of Embed interface
@@ -313,7 +314,7 @@ func (_m *MockEmbed) EmbeddedMethod() {
 
 // EmbeddedMethod indicates an expected call of EmbeddedMethod
 func (_mr *MockEmbedMockRecorder) EmbeddedMethod() *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "EmbeddedMethod")
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "EmbeddedMethod", reflect.TypeOf((*MockEmbed)(nil).EmbeddedMethod))
 }
 
 // ForeignEmbeddedMethod mocks base method
@@ -325,7 +326,7 @@ func (_m *MockEmbed) ForeignEmbeddedMethod() *bufio.Reader {
 
 // ForeignEmbeddedMethod indicates an expected call of ForeignEmbeddedMethod
 func (_mr *MockEmbedMockRecorder) ForeignEmbeddedMethod() *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "ForeignEmbeddedMethod")
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "ForeignEmbeddedMethod", reflect.TypeOf((*MockEmbed)(nil).ForeignEmbeddedMethod))
 }
 
 // ImplicitPackage mocks base method
@@ -335,7 +336,7 @@ func (_m *MockEmbed) ImplicitPackage(_param0 string, _param1 imp1.ImpT, _param2
 
 // ImplicitPackage indicates an expected call of ImplicitPackage
 func (_mr *MockEmbedMockRecorder) ImplicitPackage(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "ImplicitPackage", arg0, arg1, arg2, arg3, arg4)
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "ImplicitPackage", reflect.TypeOf((*MockEmbed)(nil).ImplicitPackage), arg0, arg1, arg2, arg3, arg4)
 }
 
 // RegularMethod mocks base method
@@ -345,7 +346,7 @@ func (_m *MockEmbed) RegularMethod() {
 
 // RegularMethod indicates an expected call of RegularMethod
 func (_mr *MockEmbedMockRecorder) RegularMethod() *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "RegularMethod")
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "RegularMethod", reflect.TypeOf((*MockEmbed)(nil).RegularMethod))
 }
 
 // MockEmbedded is a mock of Embedded interface
@@ -378,5 +379,5 @@ func (_m *MockEmbedded) EmbeddedMethod() {
 
 // EmbeddedMethod indicates an expected call of EmbeddedMethod
 func (_mr *MockEmbeddedMockRecorder) EmbeddedMethod() *gomock.Call {
-	return _mr.mock.ctrl.RecordCall(_mr.mock, "EmbeddedMethod")
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "EmbeddedMethod", reflect.TypeOf((*MockEmbedded)(nil).EmbeddedMethod))
 }


Test patch:
diff --git a/gomock/controller_test.go b/gomock/controller_test.go
index ac5204f..560ab0e 100644
--- a/gomock/controller_test.go
+++ b/gomock/controller_test.go
@@ -48,7 +48,7 @@ func (e *ErrorReporter) assertPass(msg string) {
 
 func (e *ErrorReporter) assertFail(msg string) {
 	if !e.failed {
-		e.t.Error("Expected failure, but got pass: %s", msg)
+		e.t.Errorf("Expected failure, but got pass: %s", msg)
 	}
 }
 
@@ -119,9 +119,14 @@ func (s *Subject) BarMethod(arg string) int {
 	return 0
 }
 
+var (
+	FooMethodType = reflect.TypeOf((*Subject).FooMethod)
+	BarMethodType = reflect.TypeOf((*Subject).BarMethod)
+)
+
 func assertEqual(t *testing.T, expected interface{}, actual interface{}) {
 	if !reflect.DeepEqual(expected, actual) {
-		t.Error("Expected %+v, but got %+v", expected, actual)
+		t.Errorf("Expected %+v, but got %+v", expected, actual)
 	}
 }
 
@@ -144,7 +149,7 @@ func TestExpectedMethodCall(t *testing.T) {
 	reporter, ctrl := createFixtures(t)
 	subject := new(Subject)
 
-	ctrl.RecordCall(subject, "FooMethod", "argument")
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "argument")
 	ctrl.Call(subject, "FooMethod", "argument")
 	ctrl.Finish()
 
@@ -166,7 +171,7 @@ func TestRepeatedCall(t *testing.T) {
 	reporter, ctrl := createFixtures(t)
 	subject := new(Subject)
 
-	ctrl.RecordCall(subject, "FooMethod", "argument").Times(3)
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "argument").Times(3)
 	ctrl.Call(subject, "FooMethod", "argument")
 	ctrl.Call(subject, "FooMethod", "argument")
 	ctrl.Call(subject, "FooMethod", "argument")
@@ -183,7 +188,7 @@ func TestUnexpectedArgCount(t *testing.T) {
 	defer reporter.recoverUnexpectedFatal()
 	subject := new(Subject)
 
-	ctrl.RecordCall(subject, "FooMethod", "argument")
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "argument")
 	reporter.assertFatal(func() {
 		// This call is made with the wrong number of arguments...
 		ctrl.Call(subject, "FooMethod", "argument", "extra_argument")
@@ -202,7 +207,7 @@ func TestAnyTimes(t *testing.T) {
 	reporter, ctrl := createFixtures(t)
 	subject := new(Subject)
 
-	ctrl.RecordCall(subject, "FooMethod", "argument").AnyTimes()
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "argument").AnyTimes()
 	for i := 0; i < 100; i++ {
 		ctrl.Call(subject, "FooMethod", "argument")
 	}
@@ -214,7 +219,7 @@ func TestMinTimes1(t *testing.T) {
 	// It fails if there are no calls
 	reporter, ctrl := createFixtures(t)
 	subject := new(Subject)
-	ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(1)
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "argument").MinTimes(1)
 	reporter.assertFatal(func() {
 		ctrl.Finish()
 	})
@@ -222,14 +227,14 @@ func TestMinTimes1(t *testing.T) {
 	// It succeeds if there is one call
 	reporter, ctrl = createFixtures(t)
 	subject = new(Subject)
-	ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(1)
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "argument").MinTimes(1)
 	ctrl.Call(subject, "FooMethod", "argument")
 	ctrl.Finish()
 
 	// It succeeds if there are many calls
 	reporter, ctrl = createFixtures(t)
 	subject = new(Subject)
-	ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(1)
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "argument").MinTimes(1)
 	for i := 0; i < 100; i++ {
 		ctrl.Call(subject, "FooMethod", "argument")
 	}
@@ -240,20 +245,20 @@ func TestMaxTimes1(t *testing.T) {
 	// It succeeds if there are no calls
 	_, ctrl := createFixtures(t)
 	subject := new(Subject)
-	ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(1)
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "argument").MaxTimes(1)
 	ctrl.Finish()
 
 	// It succeeds if there is one call
 	_, ctrl = createFixtures(t)
 	subject = new(Subject)
-	ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(1)
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "argument").MaxTimes(1)
 	ctrl.Call(subject, "FooMethod", "argument")
 	ctrl.Finish()
 
 	//It fails if there are more
 	reporter, ctrl := createFixtures(t)
 	subject = new(Subject)
-	ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(1)
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "argument").MaxTimes(1)
 	ctrl.Call(subject, "FooMethod", "argument")
 	reporter.assertFatal(func() {
 		ctrl.Call(subject, "FooMethod", "argument")
@@ -265,7 +270,7 @@ func TestMinMaxTimes(t *testing.T) {
 	// It fails if there are less calls than specified
 	reporter, ctrl := createFixtures(t)
 	subject := new(Subject)
-	ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(2).MaxTimes(2)
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "argument").MinTimes(2).MaxTimes(2)
 	ctrl.Call(subject, "FooMethod", "argument")
 	reporter.assertFatal(func() {
 		ctrl.Finish()
@@ -274,7 +279,7 @@ func TestMinMaxTimes(t *testing.T) {
 	// It fails if there are more calls than specified
 	reporter, ctrl = createFixtures(t)
 	subject = new(Subject)
-	ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(2).MaxTimes(2)
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "argument").MinTimes(2).MaxTimes(2)
 	ctrl.Call(subject, "FooMethod", "argument")
 	ctrl.Call(subject, "FooMethod", "argument")
 	reporter.assertFatal(func() {
@@ -284,7 +289,7 @@ func TestMinMaxTimes(t *testing.T) {
 	// It succeeds if there is just the right number of calls
 	reporter, ctrl = createFixtures(t)
 	subject = new(Subject)
-	ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(2).MinTimes(2)
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "argument").MaxTimes(2).MinTimes(2)
 	ctrl.Call(subject, "FooMethod", "argument")
 	ctrl.Call(subject, "FooMethod", "argument")
 	ctrl.Finish()
@@ -296,7 +301,7 @@ func TestDo(t *testing.T) {
 
 	doCalled := false
 	var argument string
-	ctrl.RecordCall(subject, "FooMethod", "argument").Do(
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "argument").Do(
 		func(arg string) {
 			doCalled = true
 			argument = arg
@@ -322,8 +327,8 @@ func TestReturn(t *testing.T) {
 	subject := new(Subject)
 
 	// Unspecified return should produce "zero" result.
-	ctrl.RecordCall(subject, "FooMethod", "zero")
-	ctrl.RecordCall(subject, "FooMethod", "five").Return(5)
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "zero")
+	ctrl.RecordCall(subject, "FooMethod", FooMethodType, "five").Return(5)
 
 	assertEqual(
 		t,
@@ -343,10 +348,10 @@ func TestUnorderedCalls(t *testing.T) {
 	subjectTwo := new(Subject)
 	subjectOne := new(Subject)
 
-	ctrl.RecordCall(subjectOne, "FooMethod", "1")
-	ctrl.RecordCall(subjectOne, "BarMethod", "2")
-	ctrl.RecordCall(subjectTwo, "FooMethod", "3")
-	ctrl.RecordCall(subjectTwo, "BarMethod", "4")
+	ctrl.RecordCall(subjectOne, "FooMethod", FooMethodType, "1")
+	ctrl.RecordCall(subjectOne, "BarMethod", BarMethodType, "2")
+	ctrl.RecordCall(subjectTwo, "FooMethod", FooMethodType, "3")
+	ctrl.RecordCall(subjectTwo, "BarMethod", BarMethodType, "4")
 
 	// Make the calls in a different order, which should be fine.
 	ctrl.Call(subjectOne, "BarMethod", "2")
@@ -368,9 +373,9 @@ func commonTestOrderedCalls(t *testing.T) (reporter *ErrorReporter, ctrl *gomock
 	subjectTwo = new(Subject)
 
 	gomock.InOrder(
-		ctrl.RecordCall(subjectOne, "FooMethod", "1").AnyTimes(),
-		ctrl.RecordCall(subjectTwo, "FooMethod", "2"),
-		ctrl.RecordCall(subjectTwo, "BarMethod", "3"),
+		ctrl.RecordCall(subjectOne, "FooMethod", FooMethodType, "1").AnyTimes(),
+		ctrl.RecordCall(subjectTwo, "FooMethod", FooMethodType, "2"),
+		ctrl.RecordCall(subjectTwo, "BarMethod", BarMethodType, "3"),
 	)
 
 	return
@@ -423,9 +428,9 @@ func TestCallAfterLoopPanic(t *testing.T) {
 
 	subject := new(Subject)
 
-	firstCall := ctrl.RecordCall(subject, "Foo", "1")
-	secondCall := ctrl.RecordCall(subject, "Foo", "2")
-	thirdCall := ctrl.RecordCall(subject, "Foo", "3")
+	firstCall := ctrl.RecordCall(subject, "FooMethod", FooMethodType, "1")
+	secondCall := ctrl.RecordCall(subject, "FooMethod", FooMethodType, "2")
+	thirdCall := ctrl.RecordCall(subject, "FooMethod", FooMethodType, "3")
 
 	gomock.InOrder(firstCall, secondCall, thirdCall)
 
@@ -445,7 +450,7 @@ func TestPanicOverridesExpectationChecks(t *testing.T) {
 	reporter := NewErrorReporter(t)
 
 	reporter.assertFatal(func() {
-		ctrl.RecordCall(new(Subject), "FooMethod", "1")
+		ctrl.RecordCall(new(Subject), "FooMethod", FooMethodType, "1")
 		defer ctrl.Finish()
 		reporter.Fatalf("Intentional panic")
 	})
@@ -458,7 +463,7 @@ func TestSetArgWithBadType(t *testing.T) {
 	s := new(Subject)
 	// This should catch a type error:
 	rep.assertFatal(func() {
-		ctrl.RecordCall(s, "FooMethod", "1").SetArg(0, "blah")
+		ctrl.RecordCall(s, "FooMethod", FooMethodType, "1").SetArg(0, "blah")
 	})
 	ctrl.Call(s, "FooMethod", "1")
 }
@@ -468,7 +473,7 @@ func TestTimes0(t *testing.T) {
 	defer ctrl.Finish()
 
 	s := new(Subject)
-	ctrl.RecordCall(s, "FooMethod", "arg").Times(0)
+	ctrl.RecordCall(s, "FooMethod", FooMethodType, "arg").Times(0)
 	rep.assertFatal(func() {
 		ctrl.Call(s, "FooMethod", "arg")
 	})
diff --git a/mockgen/tests/unexported_method/README.md b/mockgen/tests/unexported_method/README.md
new file mode 100644
index 0000000..87f91d4
--- /dev/null
+++ b/mockgen/tests/unexported_method/README.md
@@ -0,0 +1,1 @@
+From #52, this tests an unexported method in the mocked interface.
diff --git a/mockgen/tests/unexported_method/bugreport.go b/mockgen/tests/unexported_method/bugreport.go
new file mode 100644
index 0000000..91d5baf
--- /dev/null
+++ b/mockgen/tests/unexported_method/bugreport.go
@@ -0,0 +1,15 @@
+//go:generate mockgen -destination bugreport_mock.go -package bugreport -source=bugreport.go Example
+
+package bugreport
+
+import "fmt"
+
+// Example is an interface with a non exported method
+type Example interface {
+	someMethod(string) string
+}
+
+// CallExample is a simple function that uses the interface
+func CallExample(e Example) {
+	fmt.Println(e.someMethod("test"))
+}
diff --git a/mockgen/tests/unexported_method/bugreport_mock.go b/mockgen/tests/unexported_method/bugreport_mock.go
new file mode 100644
index 0000000..8f30bbe
--- /dev/null
+++ b/mockgen/tests/unexported_method/bugreport_mock.go
@@ -0,0 +1,44 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: bugreport.go
+
+package bugreport
+
+import (
+	gomock "github.com/golang/mock/gomock"
+	reflect "reflect"
+)
+
+// MockExample is a mock of Example interface
+type MockExample struct {
+	ctrl     *gomock.Controller
+	recorder *MockExampleMockRecorder
+}
+
+// MockExampleMockRecorder is the mock recorder for MockExample
+type MockExampleMockRecorder struct {
+	mock *MockExample
+}
+
+// NewMockExample creates a new mock instance
+func NewMockExample(ctrl *gomock.Controller) *MockExample {
+	mock := &MockExample{ctrl: ctrl}
+	mock.recorder = &MockExampleMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use
+func (_m *MockExample) EXPECT() *MockExampleMockRecorder {
+	return _m.recorder
+}
+
+// someMethod mocks base method
+func (_m *MockExample) someMethod(_param0 string) string {
+	ret := _m.ctrl.Call(_m, "someMethod", _param0)
+	ret0, _ := ret[0].(string)
+	return ret0
+}
+
+// someMethod indicates an expected call of someMethod
+func (_mr *MockExampleMockRecorder) someMethod(arg0 interface{}) *gomock.Call {
+	return _mr.mock.ctrl.RecordCall(_mr.mock, "someMethod", reflect.TypeOf((*MockExample)(nil).someMethod), arg0)
+}
diff --git a/mockgen/tests/unexported_method/bugreport_test.go b/mockgen/tests/unexported_method/bugreport_test.go
new file mode 100644
index 0000000..d428fb4
--- /dev/null
+++ b/mockgen/tests/unexported_method/bugreport_test.go
@@ -0,0 +1,17 @@
+package bugreport
+
+import (
+	"testing"
+
+	"github.com/golang/mock/gomock"
+)
+
+func TestCallExample(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	e := NewMockExample(ctrl)
+	e.EXPECT().someMethod(gomock.Any()).Return("it works!")
+
+	CallExample(e)
+}