1// A test that uses a mock. 2package user_test 3 4import ( 5 "testing" 6 7 "github.com/golang/mock/gomock" 8 user "github.com/golang/mock/sample" 9 "github.com/golang/mock/sample/imp1" 10 mock_user "github.com/golang/mock/sample/mock_user" 11) 12 13func TestRemember(t *testing.T) { 14 ctrl := gomock.NewController(t) 15 defer ctrl.Finish() 16 17 mockIndex := mock_user.NewMockIndex(ctrl) 18 mockIndex.EXPECT().Put("a", 1) // literals work 19 mockIndex.EXPECT().Put("b", gomock.Eq(2)) // matchers work too 20 21 // NillableRet returns error. Not declaring it should result in a nil return. 22 mockIndex.EXPECT().NillableRet() 23 // Calls that returns something assignable to the return type. 24 boolc := make(chan bool) 25 // In this case, "chan bool" is assignable to "chan<- bool". 26 mockIndex.EXPECT().ConcreteRet().Return(boolc) 27 // In this case, nil is assignable to "chan<- bool". 28 mockIndex.EXPECT().ConcreteRet().Return(nil) 29 30 // Should be able to place expectations on variadic methods. 31 mockIndex.EXPECT().Ellip("%d", 0, 1, 1, 2, 3) // direct args 32 tri := []interface{}{1, 3, 6, 10, 15} 33 mockIndex.EXPECT().Ellip("%d", tri...) // args from slice 34 mockIndex.EXPECT().EllipOnly(gomock.Eq("arg")) 35 36 user.Remember(mockIndex, []string{"a", "b"}, []interface{}{1, 2}) 37 // Check the ConcreteRet calls. 38 if c := mockIndex.ConcreteRet(); c != boolc { 39 t.Errorf("ConcreteRet: got %v, want %v", c, boolc) 40 } 41 if c := mockIndex.ConcreteRet(); c != nil { 42 t.Errorf("ConcreteRet: got %v, want nil", c) 43 } 44 45 // Try one with an action. 46 calledString := "" 47 mockIndex.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(key string, _ interface{}) { 48 calledString = key 49 }) 50 mockIndex.EXPECT().NillableRet() 51 user.Remember(mockIndex, []string{"blah"}, []interface{}{7}) 52 if calledString != "blah" { 53 t.Fatalf(`Uh oh. %q != "blah"`, calledString) 54 } 55 56 // Use Do with a nil arg. 57 mockIndex.EXPECT().Put("nil-key", gomock.Any()).Do(func(key string, value interface{}) { 58 if value != nil { 59 t.Errorf("Put did not pass through nil; got %v", value) 60 } 61 }) 62 mockIndex.EXPECT().NillableRet() 63 user.Remember(mockIndex, []string{"nil-key"}, []interface{}{nil}) 64} 65 66func TestVariadicFunction(t *testing.T) { 67 ctrl := gomock.NewController(t) 68 defer ctrl.Finish() 69 70 mockIndex := mock_user.NewMockIndex(ctrl) 71 mockIndex.EXPECT().Ellip("%d", 5, 6, 7, 8).Do(func(format string, nums ...int) { 72 sum := 0 73 for _, value := range nums { 74 sum += value 75 } 76 if sum != 26 { 77 t.Errorf("Expected 7, got %d", sum) 78 } 79 }) 80 mockIndex.EXPECT().Ellip("%d", gomock.Any()).Do(func(format string, nums ...int) { 81 sum := 0 82 for _, value := range nums { 83 sum += value 84 } 85 if sum != 10 { 86 t.Errorf("Expected 7, got %d", sum) 87 } 88 }) 89 mockIndex.EXPECT().Ellip("%d", gomock.Any()).Do(func(format string, nums ...int) { 90 sum := 0 91 for _, value := range nums { 92 sum += value 93 } 94 if sum != 0 { 95 t.Errorf("Expected 0, got %d", sum) 96 } 97 }) 98 mockIndex.EXPECT().Ellip("%d", gomock.Any()).Do(func(format string, nums ...int) { 99 sum := 0 100 for _, value := range nums { 101 sum += value 102 } 103 if sum != 0 { 104 t.Errorf("Expected 0, got %d", sum) 105 } 106 }) 107 mockIndex.EXPECT().Ellip("%d").Do(func(format string, nums ...int) { 108 sum := 0 109 for _, value := range nums { 110 sum += value 111 } 112 if sum != 0 { 113 t.Errorf("Expected 0, got %d", sum) 114 } 115 }) 116 117 mockIndex.Ellip("%d", 1, 2, 3, 4) // Match second matcher. 118 mockIndex.Ellip("%d", 5, 6, 7, 8) // Match first matcher. 119 mockIndex.Ellip("%d", 0) 120 mockIndex.Ellip("%d") 121 mockIndex.Ellip("%d") 122} 123 124func TestGrabPointer(t *testing.T) { 125 ctrl := gomock.NewController(t) 126 defer ctrl.Finish() 127 128 mockIndex := mock_user.NewMockIndex(ctrl) 129 mockIndex.EXPECT().Ptr(gomock.Any()).SetArg(0, 7) // set first argument to 7 130 131 i := user.GrabPointer(mockIndex) 132 if i != 7 { 133 t.Errorf("Expected 7, got %d", i) 134 } 135} 136 137func TestEmbeddedInterface(t *testing.T) { 138 ctrl := gomock.NewController(t) 139 defer ctrl.Finish() 140 141 mockEmbed := mock_user.NewMockEmbed(ctrl) 142 mockEmbed.EXPECT().RegularMethod() 143 mockEmbed.EXPECT().EmbeddedMethod() 144 mockEmbed.EXPECT().ForeignEmbeddedMethod() 145 146 mockEmbed.RegularMethod() 147 mockEmbed.EmbeddedMethod() 148 var emb imp1.ForeignEmbedded = mockEmbed // also does interface check 149 emb.ForeignEmbeddedMethod() 150} 151 152func TestExpectTrueNil(t *testing.T) { 153 // Make sure that passing "nil" to EXPECT (thus as a nil interface value), 154 // will correctly match a nil concrete type. 155 ctrl := gomock.NewController(t) 156 defer ctrl.Finish() 157 158 mockIndex := mock_user.NewMockIndex(ctrl) 159 mockIndex.EXPECT().Ptr(nil) // this nil is a nil interface{} 160 mockIndex.Ptr(nil) // this nil is a nil *int 161} 162 163func TestDoAndReturnSignature(t *testing.T) { 164 t.Run("wrong number of return args", func(t *testing.T) { 165 ctrl := gomock.NewController(t) 166 defer ctrl.Finish() 167 168 mockIndex := mock_user.NewMockIndex(ctrl) 169 170 mockIndex.EXPECT().Slice(gomock.Any(), gomock.Any()).DoAndReturn( 171 func(_ []int, _ []byte) { 172 return 173 }) 174 175 defer func() { 176 if r := recover(); r == nil { 177 t.Error("expected panic") 178 } 179 }() 180 181 mockIndex.Slice([]int{0}, []byte("meow")) 182 }) 183 184 t.Run("wrong type of return arg", func(t *testing.T) { 185 ctrl := gomock.NewController(t) 186 defer ctrl.Finish() 187 188 mockIndex := mock_user.NewMockIndex(ctrl) 189 190 mockIndex.EXPECT().Slice(gomock.Any(), gomock.Any()).DoAndReturn( 191 func(_ []int, _ []byte) bool { 192 return true 193 }) 194 195 mockIndex.Slice([]int{0}, []byte("meow")) 196 }) 197} 198