Documentation
¶
Overview ¶
Package mm tries to minimise code change to support Dependency Injection to support mocking in unittest. The assumption it makes is very minimal, just make sure the exported methods from your lib are in a form of exported variables. So it provides a manager for your method behind the scene, if you enqueued a fake response for you test in current goroutine, calling the (managed) method will firstly response your fake response instead to calling the original. Note that, for putting minimal code footprint as one of top priority, this lib will use panic for failed assertion check (like parameter check) instead of passing err back to user that simply make final code bloated.
Index ¶
- Variables
- func EnableMock(method interface{}, name string)
- func Expect(method interface{}, response ...interface{})
- func ExpectFunc(method interface{}, fakeFunc interface{})
- func GetCurrentT() (t *testing.T)
- func GetMethodType(method interface{}) (typeMethod reflect.Type)
- func IsMethod(method interface{}) (yes bool)
- func IsMethodPointer(methodPointer interface{}) (yes bool)
- func ResetQueue(method interface{})
- func SetLogger(logger Logger)
- func SetQueueLength(newLength int)
- func ValueSliceToInterfaceSlice(valueSlice []reflect.Value) (interfaceSlice []interface{})
- type Initiator
- type Logger
- type Manager
- type ManagerMap
- type MethodUniqueID
- type OriginalMethod
- type RespQueue
Constants ¶
This section is empty.
Variables ¶
var ( // DefaultLogger is for minimal and human readable logging DefaultLogger = func(methodName string, isMockResponse bool, output []interface{}) { loggerMutex.Lock() defer loggerMutex.Unlock() var tag string if isMockResponse { tag = "[mock]" } else { tag = "[real]" } tpl := tag + " %s" t := ", %#v" t = strings.Repeat(t, len(output)) tpl += t tpl += "" output = append([]interface{}{methodName}, output...) code := pretty.Sprintf(tpl, output...) fmt.Println(code) } // CapturingLogger organise the real output in code form that you can copy paste. // It's a handy helper for converting integration test into unittest. // 1. set it as logger // 2. call "go test -v -run yourtest" CapturingLogger = func(methodName string, isMockResponse bool, output []interface{}) { if !isMockResponse { return } loggerMutex.Lock() defer loggerMutex.Unlock() tpl := "mm.Expect(&%s" t := ", %#v" t = strings.Repeat(t, len(output)) tpl += t tpl += ")" output = append([]interface{}{methodName}, output...) code := pretty.Sprintf(tpl, output...) fmt.Println(code) } )
Functions ¶
func EnableMock ¶
func EnableMock(method interface{}, name string)
EnableMock upgrades a method to allow per-goroutine mocking. Note that, 1) it will replace your method with method helper, so do it at beginning of all your unittests, not in the middle, to avoid race condition. 2) if default queue length (200) is not enough for you, you can enlarge by giving the queueLength. It panic if you gave invalid value. 3) it's expected to be called at ONLY init phase of tests, so no need to protect with Mutex
func Expect ¶
func Expect(method interface{}, response ...interface{})
Expect adds a mocking response to a queue of given method. Note that, 1) the queue is tied to current goroutine, so call from different goroutine won't see this result. 2) for the expected response, first in first out 3) if no more expected response in queue, the original function would be called to serve the call 4) you can enqueue mock objects to its constructing function 5) it panic if you gave invalid value
func ExpectFunc ¶
func ExpectFunc(method interface{}, fakeFunc interface{})
ExpectFunc adds a temp implementation of the original method and consume once It would be helpful for some special case like simulating a timeout.
func GetMethodType ¶
GetMethodType ...
func IsMethodPointer ¶
func IsMethodPointer(methodPointer interface{}) (yes bool)
IsMethodPointer ...
func ResetQueue ¶
func ResetQueue(method interface{})
ResetQueue flushed resp queue for a method under current goroutine
func SetLogger ¶
func SetLogger(logger Logger)
SetLogger Logger would be used during the test, default is disabled, you should set it up (only once) before test runs if you need it
func ValueSliceToInterfaceSlice ¶
ValueSliceToInterfaceSlice convert []reflect.Value to []interface{}
Types ¶
type Initiator ¶
type Initiator struct {
// CleanUp will do clean up gls state for current goroutine
CleanUp func()
}
type Logger ¶
Logger should be an external method for logging the captured content by default the logger is empty and capturing is disabled note: Assuming it's set once at testing beginning, it's not Mutex protected. Don't change it during test.
type Manager ¶
type Manager struct {
Name string
Method *OriginalMethod
}
Manager maintains states of a method wrapper, which will take over control of your original method. The basic idea is, for each calls it will 1) check if any expected fake response in the queue for current goroutine 2) if yes, consume the response, otherwise call original method like nothing happen
type ManagerMap ¶
type ManagerMap map[MethodUniqueID]*Manager
ManagerMap stores mapping relation from pointer of manager method to its state struct. Note that, 1) the pointer of original method is in the manager state. 2) assuming the map is formed from beginning of test and remain no changed, so no need to add sync.RWMutex protection.
type MethodUniqueID ¶
type MethodUniqueID string
MethodUniqueID is string representation of a method's identifier (memory address) in current running instance. It's not guaranteed to be the same after process restarts. For being easy to understand it use fmt pkg and a string form instead of unsafe.Pointer
func GetMethodUniqueID ¶
func GetMethodUniqueID(method interface{}) (id MethodUniqueID)
GetMethodUniqueID ...
type OriginalMethod ¶
type OriginalMethod struct {
// contains filtered or unexported fields
}
OriginalMethod ...
func OriginalMethodNew ¶
func OriginalMethodNew(methodName string, method interface{}) (o *OriginalMethod, ok bool)
OriginalMethodNew ...
func (*OriginalMethod) Apply ¶
func (o *OriginalMethod) Apply(input []reflect.Value) (output []reflect.Value)
Apply ...
func (*OriginalMethod) MakeFunc ¶
func (o *OriginalMethod) MakeFunc() (f reflect.Value)
MakeFunc ...