Documentation ¶
Overview ¶
Package vermock provides a flexible and functional mocking framework for Go tests.
Example (AllowRepeatedCalls) ¶
package main import ( "fmt" "testing" vermock "github.com/Versent/go-vermock" ) // Cache contains a variety of methods with different signatures. type Cache interface { Put(string, any) error Get(string) (any, bool) Delete(string) Load(...string) } // mockCache is a mock implementation of Cache. It can be anything, but // zero-sized types are problematic. type mockCache struct { _ byte } // Put returns one value, so use vermock.Call1. func (m *mockCache) Put(key string, value any) error { return vermock.Call1[error](m, "Put", key, value) } // Get returns two values, so use vermock.Call2. func (m *mockCache) Get(key string) (any, bool) { return vermock.Call2[any, bool](m, "Get", key) } // Delete returns no values, so use vermock.Call0. func (m *mockCache) Delete(key string) { vermock.Call0(m, "Delete", key) } // Load is variadic, the last argument must be passed as a slice to one of the // vermock.CallN functions. func (m *mockCache) Load(keys ...string) { vermock.Call0(m, "Load", keys) } func main() { t := &testing.T{} // or any testing.TB, your test does not create this // 1. Create a mock object with ExpectMany. var cache Cache = vermock.New(t, // delegate function may receive a call counter and the method arguments vermock.ExpectMany[mockCache]("Load", func(n vermock.CallCount, keys ...string) { fmt.Println("load", n, keys) }), // and testing.TB vermock.ExpectMany[mockCache]("Load", func(t testing.TB, n vermock.CallCount, keys ...string) { fmt.Println("load", n, keys) }), // or *testing.T vermock.ExpectMany[mockCache]("Load", func(t *testing.T, n vermock.CallCount, keys ...string) { fmt.Println("load", n, keys) }), // or only testing.TB/*testing.T vermock.ExpectMany[mockCache]("Load", func(t testing.TB, keys ...string) { fmt.Println("load 3", keys) }), // or only the method arguments vermock.ExpectMany[mockCache]("Load", func(keys ...string) { fmt.Println("load 4", keys) }), ) // 2. Use the mock object in your code under test. cache.Load("foo", "bar") cache.Load("baz") cache.Load("foo") cache.Load("bar") cache.Load("baz") cache.Load("foo", "bar", "baz") // 3. Assert that all expected methods were called. vermock.AssertExpectedCalls(t, cache) // mock will not fail the test because ExpectMany allows repeated calls. fmt.Println("more than expected:", t.Failed()) }
Output: load 0 [foo bar] load 1 [baz] load 2 [foo] load 3 [bar] load 4 [baz] load 4 [foo bar baz] more than expected: false
Example (MixedOrderedCalls) ¶
package main import ( "fmt" "testing" vermock "github.com/Versent/go-vermock" ) // Cache contains a variety of methods with different signatures. type Cache interface { Put(string, any) error Get(string) (any, bool) Delete(string) Load(...string) } // mockCache is a mock implementation of Cache. It can be anything, but // zero-sized types are problematic. type mockCache struct { _ byte } // Put returns one value, so use vermock.Call1. func (m *mockCache) Put(key string, value any) error { return vermock.Call1[error](m, "Put", key, value) } // Get returns two values, so use vermock.Call2. func (m *mockCache) Get(key string) (any, bool) { return vermock.Call2[any, bool](m, "Get", key) } // Delete returns no values, so use vermock.Call0. func (m *mockCache) Delete(key string) { vermock.Call0(m, "Delete", key) } // Load is variadic, the last argument must be passed as a slice to one of the // vermock.CallN functions. func (m *mockCache) Load(keys ...string) { vermock.Call0(m, "Load", keys) } func main() { t := &exampleT{} // or any testing.TB, your test does not create this // 1. Create a mock object with ExpectInOrder. get := vermock.Expect[mockCache]("Get", func(key string) (any, bool) { return "bar", true }) put := vermock.Expect[mockCache]("Put", func(key string, value any) error { return nil }) var cache Cache = vermock.New(t, get, put, vermock.ExpectInOrder(put, get), get, put, ) // 2. Use the mock object in your code under test. for i := 0; i < 3; i++ { cache.Put(fmt.Sprint("foo", i), "bar") cache.Get(fmt.Sprint("foo", i)) } // 3. Assert that all expected methods were called. vermock.AssertExpectedCalls(t, cache) // mock will not fail the test fmt.Println("less than expected:", t.Failed()) } type exampleT struct { testing.T } func (t *exampleT) Fatal(args ...any) { fmt.Println(args...) t.T.FailNow() } func (t *exampleT) Fatalf(format string, args ...any) { fmt.Printf(format+"\n", args...) t.T.FailNow() } func (t *exampleT) Error(args ...any) { fmt.Println(args...) t.T.Fail() } func (t *exampleT) Errorf(format string, args ...any) { fmt.Printf(format+"\n", args...) t.T.Fail() } func (t *exampleT) Log(args ...any) { fmt.Println(args...) } func (t *exampleT) Logf(format string, args ...any) { fmt.Printf(format+"\n", args...) }
Output: call to Put: 0/0 call to Get: 0/0 call to Put: 1/1 call to Get: 1/2 call to Put: 2/2 call to Get: 2/2 less than expected: false
Example (OrderedCalls) ¶
package main import ( "fmt" "testing" vermock "github.com/Versent/go-vermock" ) // Cache contains a variety of methods with different signatures. type Cache interface { Put(string, any) error Get(string) (any, bool) Delete(string) Load(...string) } // mockCache is a mock implementation of Cache. It can be anything, but // zero-sized types are problematic. type mockCache struct { _ byte } // Put returns one value, so use vermock.Call1. func (m *mockCache) Put(key string, value any) error { return vermock.Call1[error](m, "Put", key, value) } // Get returns two values, so use vermock.Call2. func (m *mockCache) Get(key string) (any, bool) { return vermock.Call2[any, bool](m, "Get", key) } // Delete returns no values, so use vermock.Call0. func (m *mockCache) Delete(key string) { vermock.Call0(m, "Delete", key) } // Load is variadic, the last argument must be passed as a slice to one of the // vermock.CallN functions. func (m *mockCache) Load(keys ...string) { vermock.Call0(m, "Load", keys) } func main() { t := &testing.T{} // or any testing.TB, your test does not create this // 1. Create a mock object with ExpectInOrder. var cache Cache = vermock.New(t, vermock.ExpectInOrder( vermock.Expect[mockCache]("Put", func(key string, value any) error { fmt.Println("put", key, value) return nil }), vermock.Expect[mockCache]("Get", func(key string) (any, bool) { fmt.Println("get", key) return "bar", true }), ), ) // 2. Use the mock object in your code under test. cache.Get("foo") cache.Put("foo", "bar") // 3. Assert that all expected methods were called. vermock.AssertExpectedCalls(t, cache) // mock will fail the test because the call to Get is before the call // to Put. fmt.Println("less than expected:", t.Failed()) }
Output: get foo put foo bar less than expected: true
Example (Pass) ¶
package main import ( "fmt" "testing" vermock "github.com/Versent/go-vermock" ) // Cache contains a variety of methods with different signatures. type Cache interface { Put(string, any) error Get(string) (any, bool) Delete(string) Load(...string) } // mockCache is a mock implementation of Cache. It can be anything, but // zero-sized types are problematic. type mockCache struct { _ byte } // Put returns one value, so use vermock.Call1. func (m *mockCache) Put(key string, value any) error { return vermock.Call1[error](m, "Put", key, value) } // Get returns two values, so use vermock.Call2. func (m *mockCache) Get(key string) (any, bool) { return vermock.Call2[any, bool](m, "Get", key) } // Delete returns no values, so use vermock.Call0. func (m *mockCache) Delete(key string) { vermock.Call0(m, "Delete", key) } // Load is variadic, the last argument must be passed as a slice to one of the // vermock.CallN functions. func (m *mockCache) Load(keys ...string) { vermock.Call0(m, "Load", keys) } // ExpectDelete is a helper function that hides the stringiness of vermock. func ExpectDelete(delegate func(t testing.TB, key string)) func(*mockCache) { return vermock.Expect[mockCache]("Delete", delegate) } func main() { t := &exampleT{} // or any testing.TB, your test does not create this // 1. Create a mock object with expected calls. var cache Cache = vermock.New(t, // delegate function can receive testing.TB vermock.Expect[mockCache]("Get", func(t testing.TB, key string) (any, bool) { return "bar", true }), vermock.Expect[mockCache]("Put", func(t testing.TB, key string, value any) error { return nil }), // or only the method arguments vermock.Expect[mockCache]("Delete", func(key string) {}), // you may prefer to define a helper function ExpectDelete(func(t testing.TB, key string) {}), ) // 2. Use the mock object in your code under test. cache.Put("foo", "bar") cache.Get("foo") cache.Delete("foo") cache.Delete("foo") // 3. Assert that all expected methods were called. vermock.AssertExpectedCalls(t, cache) // mock will not fail the test fmt.Println("less than expected:", t.Failed()) } type exampleT struct { testing.T } func (t *exampleT) Fatal(args ...any) { fmt.Println(args...) t.T.FailNow() } func (t *exampleT) Fatalf(format string, args ...any) { fmt.Printf(format+"\n", args...) t.T.FailNow() } func (t *exampleT) Error(args ...any) { fmt.Println(args...) t.T.Fail() } func (t *exampleT) Errorf(format string, args ...any) { fmt.Printf(format+"\n", args...) t.T.Fail() } func (t *exampleT) Log(args ...any) { fmt.Println(args...) } func (t *exampleT) Logf(format string, args ...any) { fmt.Printf(format+"\n", args...) }
Output: call to Put: 0/0 call to Get: 0/0 call to Delete: 0/0 call to Delete: 1/0 less than expected: false
Example (UnexpectedCall) ¶
package main import ( "fmt" "testing" vermock "github.com/Versent/go-vermock" ) // Cache contains a variety of methods with different signatures. type Cache interface { Put(string, any) error Get(string) (any, bool) Delete(string) Load(...string) } // mockCache is a mock implementation of Cache. It can be anything, but // zero-sized types are problematic. type mockCache struct { _ byte } // Put returns one value, so use vermock.Call1. func (m *mockCache) Put(key string, value any) error { return vermock.Call1[error](m, "Put", key, value) } // Get returns two values, so use vermock.Call2. func (m *mockCache) Get(key string) (any, bool) { return vermock.Call2[any, bool](m, "Get", key) } // Delete returns no values, so use vermock.Call0. func (m *mockCache) Delete(key string) { vermock.Call0(m, "Delete", key) } // Load is variadic, the last argument must be passed as a slice to one of the // vermock.CallN functions. func (m *mockCache) Load(keys ...string) { vermock.Call0(m, "Load", keys) } func main() { t := &testing.T{} // or any testing.TB, your test does not create this // 1. Create a mock object with expected calls. var cache Cache = vermock.New(t, // delegate function can receive testing.TB vermock.Expect[mockCache]("Put", func(t testing.TB, key string, value any) error { fmt.Println("put", key, value) return nil }), // or only the method arguments vermock.Expect[mockCache]("Delete", func(key string) { fmt.Println("delete", key) }), ) // 2. Use the mock object in your code under test. cache.Put("foo", "bar") cache.Get("foo") cache.Delete("foo") // 3. Assert that all expected methods were called. vermock.AssertExpectedCalls(t, cache) // mock will fail the test because the call to Get is not expected. fmt.Println("more than expected:", t.Failed()) }
Output: put foo bar delete foo more than expected: true
Example (UnmetExpectation) ¶
package main import ( "fmt" "testing" vermock "github.com/Versent/go-vermock" ) // Cache contains a variety of methods with different signatures. type Cache interface { Put(string, any) error Get(string) (any, bool) Delete(string) Load(...string) } // mockCache is a mock implementation of Cache. It can be anything, but // zero-sized types are problematic. type mockCache struct { _ byte } // Put returns one value, so use vermock.Call1. func (m *mockCache) Put(key string, value any) error { return vermock.Call1[error](m, "Put", key, value) } // Get returns two values, so use vermock.Call2. func (m *mockCache) Get(key string) (any, bool) { return vermock.Call2[any, bool](m, "Get", key) } // Delete returns no values, so use vermock.Call0. func (m *mockCache) Delete(key string) { vermock.Call0(m, "Delete", key) } // Load is variadic, the last argument must be passed as a slice to one of the // vermock.CallN functions. func (m *mockCache) Load(keys ...string) { vermock.Call0(m, "Load", keys) } // ExpectDelete is a helper function that hides the stringiness of vermock. func ExpectDelete(delegate func(t testing.TB, key string)) func(*mockCache) { return vermock.Expect[mockCache]("Delete", delegate) } func main() { t := &testing.T{} // or any testing.TB, your test does not create this // 1. Create a mock object with expected calls. var cache Cache = vermock.New(t, // delegate function can receive testing.TB vermock.Expect[mockCache]("Put", func(t testing.TB, key string, value any) error { fmt.Println("put", key, value) return nil }), // or *testing.T vermock.Expect[mockCache]("Get", func(t *testing.T, key string) (any, bool) { fmt.Println("get", key) return "bar", true }), // or only the method arguments vermock.Expect[mockCache]("Delete", func(key string) { fmt.Println("delete", key) }), // you may prefer to define a helper function ExpectDelete(func(t testing.TB, key string) { t.Log("this is not going to be called; causing t.Fail() to be called by vermock.AssertExpectedCalls") }), ) // 2. Use the mock object in your code under test. cache.Put("foo", "bar") cache.Get("foo") cache.Delete("foo") // 3. Assert that all expected methods were called. vermock.AssertExpectedCalls(t, cache) // mock will fail the test because the second call to Delete is not met. fmt.Println("less than expected:", t.Failed()) }
Output: put foo bar get foo delete foo less than expected: true
Index ¶
- func AssertExpectedCalls(t testing.TB, mocks ...any)
- func Call0[T any](key *T, name string, in ...any)
- func Call1[T1, T any](key *T, name string, in ...any) (v T1)
- func Call2[T1, T2, T any](key *T, name string, in ...any) (v1 T1, v2 T2)
- func Call3[T1, T2, T3, T any](key *T, name string, in ...any) (v1 T1, v2 T2, v3 T3)
- func Call4[T1, T2, T3, T4, T any](key *T, name string, in ...any) (v1 T1, v2 T2, v3 T3, v4 T4)
- func Call5[T1, T2, T3, T4, T5, T any](key *T, name string, in ...any) (v1 T1, v2 T2, v3 T3, v4 T4, v5 T5)
- func Call6[T1, T2, T3, T4, T5, T6, T any](key *T, name string, in ...any) (v1 T1, v2 T2, v3 T3, v4 T4, v5 T5, v6 T6)
- func Call7[T1, T2, T3, T4, T5, T6, T7, T any](key *T, name string, in ...any) (v1 T1, v2 T2, v3 T3, v4 T4, v5 T5, v6 T6, v7 T7)
- func Call8[T1, T2, T3, T4, T5, T6, T7, T8, T any](key *T, name string, in ...any) (v1 T1, v2 T2, v3 T3, v4 T4, v5 T5, v6 T6, v7 T7, v8 T8)
- func Call9[T1, T2, T3, T4, T5, T6, T7, T8, T9, T any](key *T, name string, in ...any) (v1 T1, v2 T2, v3 T3, v4 T4, v5 T5, v6 T6, v7 T7, v8 T8, v9 T9)
- func CallDelegate[T any](key *T, name string, outTypes []reflect.Type, in ...reflect.Value) (out []reflect.Value)
- func New[T any](t testing.TB, opts ...Option[T]) *T
- type CallCount
- type Callable
- type Callables
- type Delegate
- type Delegates
- type MultiCallable
- type Option
- type Value
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AssertExpectedCalls ¶
AssertExpectedCalls asserts that all expected callables of all delegates of the given mocks were called.
func Call0 ¶
Call0 calls the function of the given name for the given mock with the given arguments. If the function is variadic then the last argument must be passed as a slice, otherwise this function panics. The function is expected to return no result values, otherwise the will be marked as a fail and this function will panic.
func Call1 ¶
Call1 calls the function of the given name for the given mock with the given arguments. If the function is variadic then the last argument must be passed as a slice, otherwise this function panics. The function is expected to return one result value, otherwise the will be marked as a fail and this function will return an error when T1 is assignable to an error type, or this function will panic.
func Call2 ¶
Call2 calls the function of the given name for the given mock with the given arguments. If the function is variadic then the last argument must be passed as a slice, otherwise this function panics. The function is expected to return two result values, otherwise the will be marked as a fail and this function will return an error when T2 is assignable to an error type, or this function will panic.
func Call3 ¶
Call3 calls the function of the given name for the given mock with the given arguments. If the function is variadic then the last argument must be passed as a slice, otherwise this function panics. The function is expected to return three result values, otherwise the will be marked as a fail and this function will return an error when T3 is assignable to an error type, or this function will panic.
func Call4 ¶
Call4 calls the function of the given name for the given mock with the given arguments. If the function is variadic then the last argument must be passed as a slice, otherwise this function panics. The function is expected to return four result values, otherwise the will be marked as a fail and this function will return an error when T4 is assignable to an error type, or this function will panic.
func Call5 ¶
func Call5[T1, T2, T3, T4, T5, T any](key *T, name string, in ...any) (v1 T1, v2 T2, v3 T3, v4 T4, v5 T5)
Call5 calls the function of the given name for the given mock with the given arguments. If the function is variadic then the last argument must be passed as a slice, otherwise this function panics. The function is expected to return 5 result values, otherwise the will be marked as a fail and this function will return an error when T5 is assignable to an error type, or this function will panic.
func Call6 ¶
func Call6[T1, T2, T3, T4, T5, T6, T any](key *T, name string, in ...any) (v1 T1, v2 T2, v3 T3, v4 T4, v5 T5, v6 T6)
Call6 calls the function of the given name for the given mock with the given arguments. If the function is variadic then the last argument must be passed as a slice, otherwise this function panics. The function is expected to return 6 result values, otherwise the will be marked as a fail and this function will return an error when T6 is assignable to an error type, or this function will panic.
func Call7 ¶
func Call7[T1, T2, T3, T4, T5, T6, T7, T any](key *T, name string, in ...any) (v1 T1, v2 T2, v3 T3, v4 T4, v5 T5, v6 T6, v7 T7)
Call7 calls the function of the given name for the given mock with the given arguments. If the function is variadic then the last argument must be passed as a slice, otherwise this function panics. The function is expected to return 7 result values, otherwise the will be marked as a fail and this function will return an error when T7 is assignable to an error type, or this function will panic.
func Call8 ¶
func Call8[T1, T2, T3, T4, T5, T6, T7, T8, T any](key *T, name string, in ...any) (v1 T1, v2 T2, v3 T3, v4 T4, v5 T5, v6 T6, v7 T7, v8 T8)
Call8 calls the function of the given name for the given mock with the given arguments. If the function is variadic then the last argument must be passed as a slice, otherwise this function panics. The function is expected to return 8 result values, otherwise the will be marked as a fail and this function will return an error when T8 is assignable to an error type, or this function will panic.
func Call9 ¶
func Call9[T1, T2, T3, T4, T5, T6, T7, T8, T9, T any](key *T, name string, in ...any) (v1 T1, v2 T2, v3 T3, v4 T4, v5 T5, v6 T6, v7 T7, v8 T8, v9 T9)
Call9 calls the function of the given name for the given mock with the given arguments. If the function is variadic then the last argument must be passed as a slice, otherwise this function panics. The function is expected to return 9 result values, otherwise the will be marked as a fail and this function will return an error when T9 is assignable to an error type, or this function will panic.
func CallDelegate ¶
func CallDelegate[T any](key *T, name string, outTypes []reflect.Type, in ...reflect.Value) (out []reflect.Value)
CallDelegate calls the next Callable of the Delegate with the given name and given arguments. If the delegate is variadic then the last argument must be a slice, otherwise this function panics. If the next Callable does not exist or the last Callable is not MultiCallable, then the mock object will be marked as failed. In the case of a fail and if the delegate function returns an error as its last return value, then the error will be set and returned otherwise the function returns zero values for all of the return values.
Types ¶
type Callables ¶
type Callables []Callable
Callables is a slice of Callable objects.
func (Callables) Call ¶
Call invokes the Callable at the given index with the given arguments. Panics if the index is out of range and the last Callable is not a MultiCallable.
func (Callables) MultiCallable ¶
MultiCallable returns true if the last Callable in the slice is a MultiCallable.
type MultiCallable ¶
type MultiCallable interface {
MultiCallable() bool
}
MultiCallable defines an interface for Callable objects that can be called multiple times.
type Option ¶
type Option[T any] func(*T)
Option defines a function that configures a mock object.
func Expect ¶
Expect registers a function to be called exactly once when a method with the given name is invoked on the mock object. The function signature of fn must match the named method signature, except that the first argument may optionally be a testing.TB or *testing.T. Panics if fn is not a function.
func ExpectAnyOrder ¶
func ExpectInOrder ¶
func ExpectMany ¶
ExpectMany registers a function to be called at least once for a method with the given name on the mock object. Like Expect, the arguments of fn must match the named method signature and may optionally be preceded by a testing.TB or *testing.T. In addition, the first argument of fn may optionally be of type CallCount, in such cases fn will be passed the total number of times the method has been called (starting at 0). Panics if fn is not a function.