Add tests for various Do/DoAndReturn calls (#430)

This commit is contained in:
Cole Wippern 2020-07-25 19:32:24 -07:00 коммит произвёл GitHub
Родитель a5953ef0e2
Коммит 91d4b5c4fd
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 574 добавлений и 1 удалений

Просмотреть файл

@ -1,9 +1,47 @@
// Copyright 2020 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gomock
import (
"fmt"
"reflect"
"testing"
)
type foo struct{}
func (f foo) String() string {
return "meow"
}
type a struct {
name string
}
func (testObj a) Name() string {
return testObj.name
}
type b struct {
foo string
}
func (testObj b) Foo() string {
return testObj.foo
}
type mockTestReporter struct {
errorCalls int
fatalCalls int
@ -49,3 +87,502 @@ func TestCall_After(t *testing.T) {
}
})
}
func prepareDoCall(doFunc, callFunc interface{}) *Call {
tr := &mockTestReporter{}
c := &Call{
t: tr,
methodType: reflect.TypeOf(callFunc),
}
c.Do(doFunc)
return c
}
func prepareDoAndReturnCall(doFunc, callFunc interface{}) *Call {
tr := &mockTestReporter{}
c := &Call{
t: tr,
methodType: reflect.TypeOf(callFunc),
}
c.DoAndReturn(doFunc)
return c
}
type testCase struct {
description string
doFunc interface{}
callFunc interface{}
args []interface{}
expectPanic bool
}
var testCases []testCase = []testCase{
{
description: "argument to Do is not a function",
doFunc: "meow",
callFunc: func(x int, y int) {
return
},
args: []interface{}{0, 1},
expectPanic: true,
}, {
description: "argument to Do is not a function",
doFunc: "meow",
callFunc: func(x int, y int) bool {
return true
},
args: []interface{}{0, 1},
expectPanic: true,
}, {
description: "number of args for Do func don't match Call func",
doFunc: func(x int) {
return
},
callFunc: func(x int, y int) {
return
},
args: []interface{}{0, 1},
expectPanic: true,
}, {
description: "number of args for Do func don't match Call func",
doFunc: func(x int) bool {
return true
},
callFunc: func(x int, y int) bool {
return true
},
args: []interface{}{0, 1},
expectPanic: true,
}, {
description: "arg type for Do func incompatible with Call func",
doFunc: func(x int) {
return
},
callFunc: func(x string) {
return
},
args: []interface{}{"meow"},
expectPanic: true,
}, {
description: "arg type for Do func incompatible with Call func",
doFunc: func(x int) bool {
return true
},
callFunc: func(x string) bool {
return true
},
args: []interface{}{"meow"},
expectPanic: true,
}, {
description: "Do func(int) Call func(int)",
doFunc: func(x int) {
return
},
callFunc: func(x int) {
return
},
args: []interface{}{0},
}, {
description: "Do func(int) Call func(interface{})",
doFunc: func(x int) {
return
},
callFunc: func(x interface{}) {
return
},
args: []interface{}{0},
}, {
description: "Do func(int) bool Call func(int) bool",
doFunc: func(x int) bool {
return true
},
callFunc: func(x int) bool {
return true
},
args: []interface{}{0},
}, {
description: "Do func(int) bool Call func(interface{}) bool",
doFunc: func(x int) bool {
return true
},
callFunc: func(x interface{}) bool {
return true
},
args: []interface{}{0},
}, {
description: "Do func(string) Call func([]byte)",
doFunc: func(x string) {
return
},
callFunc: func(x []byte) {
return
},
args: []interface{}{[]byte("meow")},
expectPanic: true,
}, {
description: "Do func(string) bool Call func([]byte) bool",
doFunc: func(x string) bool {
return true
},
callFunc: func(x []byte) bool {
return true
},
args: []interface{}{[]byte("meow")},
expectPanic: true,
}, {
description: "Do func(map[int]string) Call func(map[interface{}]int)",
doFunc: func(x map[int]string) {
return
},
callFunc: func(x map[interface{}]int) {
return
},
args: []interface{}{map[interface{}]int{"meow": 0}},
expectPanic: true,
}, {
description: "Do func(map[int]string) Call func(map[interface{}]interface{})",
doFunc: func(x map[int]string) {
return
},
callFunc: func(x map[interface{}]interface{}) {
return
},
args: []interface{}{map[interface{}]interface{}{"meow": "meow"}},
expectPanic: true,
}, {
description: "Do func(map[int]string) bool Call func(map[interface{}]int) bool",
doFunc: func(x map[int]string) bool {
return true
},
callFunc: func(x map[interface{}]int) bool {
return true
},
args: []interface{}{map[interface{}]int{"meow": 0}},
expectPanic: true,
}, {
description: "Do func(map[int]string) bool Call func(map[interface{}]interface{}) bool",
doFunc: func(x map[int]string) bool {
return true
},
callFunc: func(x map[interface{}]interface{}) bool {
return true
},
args: []interface{}{map[interface{}]interface{}{"meow": "meow"}},
expectPanic: true,
}, {
description: "Do func([]string) Call func([]interface{})",
doFunc: func(x []string) {
return
},
callFunc: func(x []interface{}) {
return
},
args: []interface{}{[]interface{}{0}},
expectPanic: true,
}, {
description: "Do func([]string) Call func([]int)",
doFunc: func(x []string) {
return
},
callFunc: func(x []int) {
return
},
args: []interface{}{[]int{0, 1}},
expectPanic: true,
}, {
description: "Do func([]int) Call func([]int)",
doFunc: func(x []int) {
return
},
callFunc: func(x []int) {
return
},
args: []interface{}{[]int{0, 1}},
}, {
description: "Do func([]int) Call func([]interface{})",
doFunc: func(x []int) {
return
},
callFunc: func(x []interface{}) {
return
},
args: []interface{}{[]interface{}{0}},
expectPanic: true,
}, {
description: "Do func([]int) Call func(...interface{})",
doFunc: func(x []int) {
return
},
callFunc: func(x ...interface{}) {
return
},
args: []interface{}{0, 1},
expectPanic: true,
}, {
description: "Do func([]int) Call func(...int)",
doFunc: func(x []int) {
return
},
callFunc: func(x ...int) {
return
},
args: []interface{}{0, 1},
expectPanic: true,
}, {
description: "Do func([]string) bool Call func([]interface{}) bool",
doFunc: func(x []string) bool {
return true
},
callFunc: func(x []interface{}) bool {
return true
},
args: []interface{}{[]interface{}{0}},
expectPanic: true,
}, {
description: "Do func([]string) bool Call func([]int) bool",
doFunc: func(x []string) bool {
return true
},
callFunc: func(x []int) bool {
return true
},
args: []interface{}{[]int{0, 1}},
expectPanic: true,
}, {
description: "Do func([]int) bool Call func([]int) bool",
doFunc: func(x []int) bool {
return true
},
callFunc: func(x []int) bool {
return true
},
args: []interface{}{[]int{0, 1}},
}, {
description: "Do func([]int) bool Call func([]interface{}) bool",
doFunc: func(x []int) bool {
return true
},
callFunc: func(x []interface{}) bool {
return true
},
args: []interface{}{[]interface{}{0}},
expectPanic: true,
}, {
description: "Do func([]int) bool Call func(...interface{}) bool",
doFunc: func(x []int) bool {
return true
},
callFunc: func(x ...interface{}) bool {
return true
},
args: []interface{}{0, 1},
expectPanic: true,
}, {
description: "Do func([]int) bool Call func(...int) bool",
doFunc: func(x []int) bool {
return true
},
callFunc: func(x ...int) bool {
return true
},
args: []interface{}{0, 1},
expectPanic: true,
}, {
description: "Do func(...int) Call func([]int)",
doFunc: func(x ...int) {
return
},
callFunc: func(x []int) {
return
},
args: []interface{}{[]int{0, 1}},
expectPanic: true,
}, {
description: "Do func(...int) Call func([]interface{})",
doFunc: func(x ...int) {
return
},
callFunc: func(x []interface{}) {
return
},
args: []interface{}{[]interface{}{0, 1}},
expectPanic: true,
}, {
description: "Do func(...int) Call func(...interface{})",
doFunc: func(x ...int) {
return
},
callFunc: func(x ...interface{}) {
return
},
args: []interface{}{0, 1},
}, {
description: "Do func(...int) bool Call func(...int) bool",
doFunc: func(x ...int) bool {
return true
},
callFunc: func(x ...int) bool {
return true
},
args: []interface{}{0, 1},
}, {
description: "Do func(...int) bool Call func([]int) bool",
doFunc: func(x ...int) bool {
return true
},
callFunc: func(x []int) bool {
return true
},
args: []interface{}{[]int{0, 1}},
expectPanic: true,
}, {
description: "Do func(...int) bool Call func([]interface{}) bool",
doFunc: func(x ...int) bool {
return true
},
callFunc: func(x []interface{}) bool {
return true
},
args: []interface{}{[]interface{}{0, 1}},
expectPanic: true,
}, {
description: "Do func(...int) bool Call func(...interface{}) bool",
doFunc: func(x ...int) bool {
return true
},
callFunc: func(x ...interface{}) bool {
return true
},
args: []interface{}{0, 1},
}, {
description: "Do func(...int) Call func(...int)",
doFunc: func(x ...int) {
return
},
callFunc: func(x ...int) {
return
},
args: []interface{}{0, 1},
}, {
description: "Do func(foo); foo implements interface X Call func(interface X)",
doFunc: func(x foo) {
return
},
callFunc: func(x fmt.Stringer) {
return
},
args: []interface{}{foo{}},
}, {
description: "Do func(b); b does not implement interface X Call func(interface X)",
doFunc: func(x b) {
return
},
callFunc: func(x fmt.Stringer) {
return
},
args: []interface{}{foo{}},
expectPanic: true,
}, {
description: "Do func(b) Call func(a); a and b are not aliases",
doFunc: func(x b) {
return
},
callFunc: func(x a) {
return
},
args: []interface{}{a{}},
expectPanic: true,
}, {
description: "Do func(foo) bool; foo implements interface X Call func(interface X) bool",
doFunc: func(x foo) bool {
return true
},
callFunc: func(x fmt.Stringer) bool {
return true
},
args: []interface{}{foo{}},
}, {
description: "Do func(b) bool; b does not implement interface X Call func(interface X) bool",
doFunc: func(x b) bool {
return true
},
callFunc: func(x fmt.Stringer) bool {
return true
},
args: []interface{}{foo{}},
expectPanic: true,
}, {
description: "Do func(b) bool Call func(a) bool; a and b are not aliases",
doFunc: func(x b) bool {
return true
},
callFunc: func(x a) bool {
return true
},
args: []interface{}{a{}},
expectPanic: true,
}, {
description: "Do func(bool) b Call func(bool) a; a and b are not aliases",
doFunc: func(x bool) b {
return b{}
},
callFunc: func(x bool) a {
return a{}
},
args: []interface{}{true},
},
}
func TestCall_Do(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
c := prepareDoCall(tc.doFunc, tc.callFunc)
if len(c.actions) != 1 {
t.Errorf("expected %d actions but got %d", 1, len(c.actions))
}
action := c.actions[0]
if tc.expectPanic {
defer func() {
if r := recover(); r == nil {
t.Error("expected Do to panic")
}
}()
}
action(tc.args)
})
}
}
func TestCall_DoAndReturn(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
c := prepareDoAndReturnCall(tc.doFunc, tc.callFunc)
if len(c.actions) != 1 {
t.Errorf("expected %d actions but got %d", 1, len(c.actions))
}
action := c.actions[0]
if tc.expectPanic {
defer func() {
if r := recover(); r == nil {
t.Error("expected DoAndReturn to panic")
}
}()
}
action(tc.args)
})
}
}

Просмотреть файл

@ -5,7 +5,7 @@ import (
"testing"
"github.com/golang/mock/gomock"
"github.com/golang/mock/sample"
user "github.com/golang/mock/sample"
"github.com/golang/mock/sample/imp1"
mock_user "github.com/golang/mock/sample/mock_user"
)
@ -159,3 +159,39 @@ func TestExpectTrueNil(t *testing.T) {
mockIndex.EXPECT().Ptr(nil) // this nil is a nil interface{}
mockIndex.Ptr(nil) // this nil is a nil *int
}
func TestDoAndReturnSignature(t *testing.T) {
t.Run("wrong number of return args", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockIndex := mock_user.NewMockIndex(ctrl)
mockIndex.EXPECT().Slice(gomock.Any(), gomock.Any()).DoAndReturn(
func(_ []int, _ []byte) {
return
})
defer func() {
if r := recover(); r == nil {
t.Error("expected panic")
}
}()
mockIndex.Slice([]int{0}, []byte("meow"))
})
t.Run("wrong type of return arg", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockIndex := mock_user.NewMockIndex(ctrl)
mockIndex.EXPECT().Slice(gomock.Any(), gomock.Any()).DoAndReturn(
func(_ []int, _ []byte) bool {
return true
})
mockIndex.Slice([]int{0}, []byte("meow"))
})
}