Documentation ¶
Overview ¶
Package godouble is a TestDouble framework for Go.
This framework creates a TestDouble implementation of an interface which can be substituted for the real thing during tests. Interface methods can then individually be Stubbed, Mocked, Spied upon or Faked as required.
Stubs, Mocks, Spies, Fakes ¶
See the canonical sources...
* http://xunitpatterns.com/Test%20Double.html
* https://martinfowler.com/articles/mocksArentStubs.html
A Stub provides specific return values for a matching call to the method. Most useful where the return values are the primary means by which correct operation of the system under test can be verified.
package examples import ( . "github.com/lwoggardner/godouble" //Note the dot import which assists with readability "testing" ) func Test_Stub(t *testing.T) { d := NewAPIDouble(t) // A specific implementation of a TestDouble //Stub a method that receives specific arguments, to return specific values d.Stub("SomeQuery").Matching(Args(Eql("test"))).Returning(Values(Results{"result"}, nil)) // Exercise the system under test substituting d for the real API client // ... // Verify assertions to confirm the system under test behaves as expected with the given return values // ... }
A Mock is a Stub with an up-front expectation for how many times it will be called. Most useful when the return values of the method do not completely ensure correct functioning of the system under test,
func Test_Mock(t *testing.T) { d := NewAPIDouble(t) // Verify the mock expectations are met at completion defer d.Verify() //Stub a method that receives specific arguments, returns specific values and explicitly expects to be called once d.Mock("SomeQuery").Matching(Args(Eql("test"))).Returning(Values(Results{"result"}, nil)).Expect(Exactly(3)) d.Mock("OtherMethod").Expect(Never()) //Exercise... }
A Spy is a record of all calls made to a method which can be verified after exercising the system under test. Used similarly to Mock, but where you prefer to explicitly assert received arguments and call counts in the Verify phase of the test.
func Test_Spy(t *testing.T) { //Setup d := NewAPIDouble(t) spy := d.Spy("SomeQuery").Returning(Values(Results{"nothing"}, nil)) //Exercise... //Verify spy.Expect(Twice()) //All calls spy.Matching(Args(Eql("test"))).Expect(Once()) //The subset of calls with matching args }
A Fake is a Spy that provides an actual implementation of the method instead of return values. Use with caution.
func Test_Fake(t *testing.T) { //Setup d := NewAPIDouble(t) impl := func( i int, options...string) *Results { return &Results{Output: fmt.Sprintf("%s %d",strings.Join(options," "),i)} } spy := d.Fake("QueryWithOptions",impl) //Exercise... //Verify spy.Expect(Twice()) spy.Matching(Args(Eql(10))).Expect(Once()) }
Index ¶
- func AssertMethodInputs(t T, m reflect.Method, funcType reflect.Type)
- func AssertMethodOutputs(t T, m reflect.Method, funcType reflect.Type)
- func AssertMethodReturnTypes(t T, m reflect.Method, returnTypes []reflect.Type, prefixes ...interface{})
- func AssertMethodReturnValues(t T, method reflect.Method, returnValues []interface{})
- func ExpectInOrder(calls ...MockedMethodCall)
- func Verify(testDoubles ...Verifiable)
- type CombinationMatcher
- func All(matchers ...Matcher) CombinationMatcher
- func And(matchers ...Matcher) CombinationMatcher
- func Any(matchers ...Matcher) CombinationMatcher
- func Func(f interface{}, explanation ...interface{}) CombinationMatcher
- func Not(matcher Matcher) CombinationMatcher
- func Or(matchers ...Matcher) CombinationMatcher
- type Completion
- type Expectation
- type FakeMethodCall
- type Matcher
- type MatcherForMethod
- type Method
- type MethodArgsMatcher
- type MethodCall
- type MockedMethodCall
- type RecordedCalls
- type ReturnChannel
- type ReturnValues
- func Delayed(rv ReturnValues, by time.Duration, sleep ...Timewarp) ReturnValues
- func NewReturnsForMethod(t T, forMethod reflect.Method, values ...interface{}) (rv ReturnValues)
- func RandDelayed(rv ReturnValues, max time.Duration, sleep ...Timewarp) ReturnValues
- func Sequence(values ...ReturnValues) ReturnValues
- func Values(values ...interface{}) ReturnValues
- func ZeroValues(methodType reflect.Type) ReturnValues
- type ReturnsForMethod
- type SingleArgMatcher
- type SpyMethodCall
- type StubbedMethodCall
- type T
- type TestDouble
- func (d *TestDouble) DisableTrace()
- func (d *TestDouble) EnableTrace()
- func (d *TestDouble) Fake(methodName string, impl interface{}) (fake FakeMethodCall)
- func (d *TestDouble) Invoke(methodName string, args ...interface{}) []interface{}
- func (d *TestDouble) Mock(methodName string) (mock MockedMethodCall)
- func (d *TestDouble) SetDefaultCall(defaultCall func(Method) MethodCall)
- func (d *TestDouble) SetDefaultReturnValues(defaultReturns func(Method) ReturnValues)
- func (d *TestDouble) SetMatcherIntegration(forMethod MatcherForMethod)
- func (d *TestDouble) SetReturnValuesIntegration(forMethod ReturnsForMethod)
- func (d *TestDouble) Spy(methodName string) (spy SpyMethodCall)
- func (d *TestDouble) String() string
- func (d *TestDouble) Stub(methodName string) (stub StubbedMethodCall)
- func (d *TestDouble) T() T
- func (d *TestDouble) Verify()
- type Timewarp
- type ValidatingReturnValues
- type Verifiable
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AssertMethodInputs ¶
AssertMethodInputs fatally fails test t unless funcType has compatible input methods with method m
func AssertMethodOutputs ¶
AssertMethodOutputs Fatally fails test t unless funcType's return types are compatible with m's return types
func AssertMethodReturnTypes ¶
func AssertMethodReturnTypes(t T, m reflect.Method, returnTypes []reflect.Type, prefixes ...interface{})
AssertMethodReturnTypes fatally fails test t unless returnTypes are compatible with method m's return types
func AssertMethodReturnValues ¶
AssertMethodReturnValues fatally fails test t unless returnValues are compatible with method
func ExpectInOrder ¶
func ExpectInOrder(calls ...MockedMethodCall)
ExpectInOrder is shorthand to Setup that the list of calls are expected to executed in this sequence
func Verify ¶
func Verify(testDoubles ...Verifiable)
Verify is shorthand to Verify a set of TestDoubles
Types ¶
type CombinationMatcher ¶
type CombinationMatcher interface { Matcher ForMethod(t T, m reflect.Method) ForType(t T, ft reflect.Type) }
A CombinationMatcher is a Matcher than can validated usage for both methods and types
func All ¶
func All(matchers ...Matcher) CombinationMatcher
All matches if all the matcherList match (returns true for no matchers)
func And ¶
func And(matchers ...Matcher) CombinationMatcher
And matches if all the matcherList match
func Any ¶
func Any(matchers ...Matcher) CombinationMatcher
Any matches if any one of matcherList match (returns false for no matchers)
func Func ¶
func Func(f interface{}, explanation ...interface{}) CombinationMatcher
Func returns a matcher from the arbitrary function f Custom matcher methods will generally be a wrapper around Func
When used as a method args matcher f(...) bool must have a compatible argument signature with the stubbed method When used as a single arg matcher f must be a func(x T) bool where T is assignable from the equivalent arg in the stubbed method Optionally include an explanation that will be formatted to string to describes what is being matched
func Or ¶
func Or(matchers ...Matcher) CombinationMatcher
Or matches if any one of matcherList match
type Completion ¶
type Completion interface { Expectation Complete(count int) bool }
A Completion is an expectation that can indicate that further calls will fail to meet the expectation Expectations that are not also Completions are never considered complete
func AtMost ¶
func AtMost(n int) Completion
AtMost returns an expectation to be called at most n times This expectation is considered complete after being exercised n times
func Between ¶
func Between(min int, max int) Completion
Between returns a new expectation that a method is exercised at least min times and at most max times The expectation is considered complete after being exercised max times
func Exactly ¶
func Exactly(n int) Completion
Exactly returns an expectation to be called exactly n times This expectation is considered complete after being exercised n times
type Expectation ¶
An Expectation verifies a count against an expected Value
func AtLeast ¶
func AtLeast(n int) Expectation
AtLeast returns an expectation to be called at least n times
type FakeMethodCall ¶
type FakeMethodCall interface { // The full set of all recorded calls to this method available to be verified RecordedCalls MethodCall }
FakeMethodCall is a SpyMethodCall with a Fake implementation.
type Matcher ¶
type Matcher interface { //Matches returns true if the arg (or args) matches this matcher Matches(args ...interface{}) bool }
Matcher is used to match a method signature or one argument at a time
type MatcherForMethod ¶
type MatcherForMethod func(t T, m reflect.Method, chained MethodArgsMatcher, matchers ...interface{}) MethodArgsMatcher
MatcherForMethod can be used to integrate a different matching framework
type Method ¶
type Method interface { Stub() StubbedMethodCall Mock() MockedMethodCall Spy() SpyMethodCall Fake(impl interface{}) FakeMethodCall Reflect() reflect.Method }
Method is used to configure the default Double type for a given interface method.
A method's signature is available via Reflect() Stub(), Mock(), Spy(), Fake() are used to return a specific MethodCall implementation to use See TestDoubleConfigurator
type MethodArgsMatcher ¶
type MethodArgsMatcher interface { Matcher //ForMethod uses t to assert suitability of this matcher to match the method signature of m ForMethod(t T, m reflect.Method) }
MethodArgsMatcher is a Matcher that can validate usage against a reflect.Method
func Args ¶
func Args(matchers ...Matcher) MethodArgsMatcher
Args builds a method arguments matcher from a list of single ArgumentMatchers
func NewMatcherForMethod ¶
func NewMatcherForMethod(t T, forMethod reflect.Method, matchers ...interface{}) (result MethodArgsMatcher)
type MethodCall ¶
type MethodCall interface {
// contains filtered or unexported methods
}
MethodCall is an abstract interface of specific call types, Stub, Mock, Spy and Fake
type MockedMethodCall ¶
type MockedMethodCall interface { /* Matching is used to setup whether this call will match a given set of arguments. Empty matcherList list will fatally fail the test If the first matcher is a Matcher then it is used (test will fatally fail is more matcherList are sent) If the first matcher is a func then is equivalent to Matching(Matcher(matcherList[0],matcherList[1:)) Otherwise each matcher is converted to a Matcher via either Func() or Eql() and this list is sent to Args() */ Matching(matchers ...interface{}) MockedMethodCall //Setup that this call will only match if the supplied calls are already complete After(calls ...MockedMethodCall) MockedMethodCall /* Returning is used to setup return values for this call The returnValues are converted to a ReturnValues via Values() */ Returning(values ...interface{}) MockedMethodCall //Setup an expectation on the number of times this call will be invoked Expect(expect Expectation) MockedMethodCall MethodCall // contains filtered or unexported methods }
MockedMethodCall is a MethodCall that has pre-defined expectations for how often and sequence of invocations
type RecordedCalls ¶
type RecordedCalls interface { /* Matching returns the subset of calls that match Empty matcherList list will fatally fail the test If the first matcher is a Matcher then it is used (test will fatally fail is more matcherList are sent) If the first matcher is a func then is equivalent to Matching(Matcher(matcherList[0],matcherList[1:)) Otherwise each matcher is converted to a Matcher via either Func() or Eql() and this list is sent to Args() */ Matching(matchers ...interface{}) RecordedCalls /* Slice returns a subset of these calls, including call at index from, excluding call at index to (like go slice)) If necessary use NumCalls() to reference calls from the end of the slice. eg to get the last 3 calls - r.Slice(r.NumCalls() -3, r.NumCalls()) */ Slice(from int, to int) RecordedCalls // After returns the subset of these calls that were invoked after all of otherCalls After(otherCalls RecordedCalls) RecordedCalls // Expect asserts the number of calls in this set Expect(expect Expectation) // NumCalls returns the number of calls in this set. // Prefer to use Expect() rather than asserting the result of NumCalls() NumCalls() int // contains filtered or unexported methods }
RecordedCalls represents a set of recorded call invocations to be verified
type ReturnChannel ¶
type ReturnChannel interface { //Send a list of return values Send(...interface{}) //Close the channel, subsequent invocations that need values will cause the test to fail fatally Close() //Set a timeout. If the timeout expires before a Value is available on the channel // ( via Send() ) the test will fail fatally. SetTimeout(timeout time.Duration, sleeper ...Timewarp) ReturnValues }
ReturnChannel provides channel semantics for returning values from stub calls
func NewReturnChannel ¶
func NewReturnChannel(bufferSize ...int) ReturnChannel
NewReturnChannel generates return values for successive calls to a stub. It will return errors if the channel is closed
Use the optional bufferSize parameter with a non-zero Value to create a buffered channel.
Use SetTimeout() to override the default timeout of 200 ms.
type ReturnValues ¶
type ReturnValues interface { //Receive is called when a method is exercised // // non nil error response will fatally terminate the test Receive() ([]interface{}, error) }
ReturnValues implementations generate values in response to Stub, Mock or Spy method invocations
func Delayed ¶
func Delayed(rv ReturnValues, by time.Duration, sleep ...Timewarp) ReturnValues
Delayed wraps the ReturnValues rv with a fixed delay of 'by' duration
Useful to simulate an asynchronous IO request, allowing other goroutines to run while waiting for the response.
An optional sleeper function, defaulting to time.Sleep, can be provided. eg for use with fake clock
func NewReturnsForMethod ¶
func NewReturnsForMethod(t T, forMethod reflect.Method, values ...interface{}) (rv ReturnValues)
func RandDelayed ¶
func RandDelayed(rv ReturnValues, max time.Duration, sleep ...Timewarp) ReturnValues
RandDelayed wraps the ReturnValues rv with a delay of up to 'max' duration
func Sequence ¶
func Sequence(values ...ReturnValues) ReturnValues
Sequence returns values from each of 'values' until there are no further values available
func Values ¶
func Values(values ...interface{}) ReturnValues
Values stores a fixed set of values returned for every invocation
func ZeroValues ¶
func ZeroValues(methodType reflect.Type) ReturnValues
ZeroValues repeatedly returns the zeroed values for the given methodType
type ReturnsForMethod ¶
type ReturnsForMethod func(t T, m reflect.Method, chained ReturnValues, returnValues ...interface{}) ReturnValues
ReturnsForMethod can be used to integrate a different return values framework
type SingleArgMatcher ¶
type SingleArgMatcher interface { Matcher //ForType uses t to assert suitability of this matcher to match a single argument of type ft ForType(t T, ft reflect.Type) }
A SingleArgMatcher is a Matcher that can validate usage against a reflect.Type
func Eql ¶
func Eql(v interface{}) SingleArgMatcher
Eql matches a single argument v via reflect.DeepEqual
func IsA ¶
func IsA(t interface{}) SingleArgMatcher
IsA matches a single argument if the supplied argument is AssignableTo or Implements the reflect.Type t
if t is not already a reflect.Type it will be converted with reflect.TypeOf
func Len ¶
func Len(v interface{}) SingleArgMatcher
Len matches a single argument that is type Array,Chan,Map,Slice,String type that have length matching v
l may be anything that can match an int eg
Len(0) Len(func(l int) bool { l <= 10})
func Nil ¶
func Nil() SingleArgMatcher
Nil matches a single argument of any nil-able type to be nil (or equivalent)
func Slice ¶
func Slice(matchers ...Matcher) SingleArgMatcher
Slice returns a Matcher for a Slice type from a list of other SingleArgumentMatchers
If all the matcherList match the argument in the corresponding position of the newSliceMatcher
type SpyMethodCall ¶
type SpyMethodCall interface { /* Returning is used to setup return values for this call The returnValues are converted to a ReturnValues via Values() */ Returning(values ...interface{}) SpyMethodCall // The full set of all recorded calls to this method available to be verified RecordedCalls MethodCall }
SpyMethodCall is a MethodCall that records method invocations for later verification
type StubbedMethodCall ¶
type StubbedMethodCall interface { /* Matching is used to setup whether this call will match a given set of arguments. Empty matcherList list will fatally fail the test If the first matcher is a Matcher then it is used (test will fatally fail is more matcherList are sent) If the first matcher is a func then is equivalent to Matching(Matcher(matcherList[0],matcherList[1:)) Otherwise each matcher is converted to a Matcher via either Func() or Eql() and this list is sent to Args() */ Matching(matchers ...interface{}) StubbedMethodCall /* Returning is used to setup return values for this call The returnValues are converted to a ReturnValues via Values() */ Returning(returnValues ...interface{}) StubbedMethodCall MethodCall }
StubbedMethodCall is a MethodCall that matches a given set of arguments and returns pre-defined values.
type T ¶
type T interface { Errorf(format string, args ...interface{}) Fatalf(format string, args ...interface{}) Logf(format string, args ...interface{}) Helper() }
T is compatible with builtin testing.T
type TestDouble ¶
type TestDouble struct {
// contains filtered or unexported fields
}
A TestDouble is an object that can substitute for a concrete implementation of an interface in a 4 phase testing framework (Setup, Exercise, Verify, Teardown).
Setup phase ¶
Expected method calls to the double can be configured as one of the following types.
1) Stub - Returns known values in response to calls against matching input arguments
2) Mock - A stub with pre-built expectations about the number and order of method invocations on matching calls
3) Spy - A stub that records calls as they execute
4) Fake - A substitute implementation for the method
Exercise phase ¶
Any methods invoked on the double are sent to the first matching call that has been configured. If no matching call is available, the DefaultMethodCallType for this double is generated.
Verify phase ¶
The Verify() method is used to confirm expectations on Mock methods have been met.
Spies (and Fakes) have explicit methods to assert the number and order of method invocations on subsets of calls.
func NewDouble ¶
func NewDouble(t T, forInterface interface{}, configurators ...func(*TestDouble)) *TestDouble
NewDouble Constructor for TestDouble called by specific implementation of test doubles.
forInterface is expected to be the nil implementation of an interface - (*Iface)(nil)
configurators are used to configure tracing and default behaviour for unregistered method calls and return values
func (*TestDouble) DisableTrace ¶ added in v0.0.2
func (d *TestDouble) DisableTrace()
func (*TestDouble) EnableTrace ¶
func (d *TestDouble) EnableTrace()
Enable tracing of all received method calls (via T.Logf)
func (*TestDouble) Fake ¶
func (d *TestDouble) Fake(methodName string, impl interface{}) (fake FakeMethodCall)
Fake installs a user implementation for the method.
Setup Phase ¶
Install the Fake implementation, which must match the signature of the method.
Only one fake is installed for a method, and clobbers any other configured calls.
Exercise Phase ¶
Invokes the fake function via reflection, and records the call as per Spy.
Verify Phase ¶
Explicitly verify RecordedCalls as per Spy.
func (*TestDouble) Invoke ¶
func (d *TestDouble) Invoke(methodName string, args ...interface{}) []interface{}
Invoke is called by specialised mock implementations, and sometimes by Fake implementations to record the invocation of a method.
func (*TestDouble) Mock ¶
func (d *TestDouble) Mock(methodName string) (mock MockedMethodCall)
Mock adds and returns a MockedMethodCall for methodName on TestDouble d
Setup Phase ¶
Configure Matcher, sequencing (After), and Return Values.
Set Expectation on number of matching invocations.
By default a MockedMethodCall matches any arguments, returns zero values for all outputs and expects exactly one invocation.
Exercise Phase ¶
The first mock matching the invocation arguments and not yet Complete in terms of Expectation will provide the output values.
Verify Phase ¶
(via call to a TestDouble.Verify() usually deferred immediately after the double is created)
Will assert the Expectation is met.
func (*TestDouble) SetDefaultCall ¶
func (d *TestDouble) SetDefaultCall(defaultCall func(Method) MethodCall)
SetDefaultCall allows caller to provide a function to decide whether to Stub, Mock, Spy or Fake a call that was not explicitly registered in Setup phase.
the default function is a mock that never expects to be called.
func (*TestDouble) SetDefaultReturnValues ¶
func (d *TestDouble) SetDefaultReturnValues(defaultReturns func(Method) ReturnValues)
SetDefaultReturnValues allows a caller to provide a function to generate default return values for a Stub, Mock, or Spy that was not explicitly registered with ReturnValues during Setup. The default is to used zeroed values via reflection.
func (*TestDouble) SetMatcherIntegration ¶
func (d *TestDouble) SetMatcherIntegration(forMethod MatcherForMethod)
func (*TestDouble) SetReturnValuesIntegration ¶
func (d *TestDouble) SetReturnValuesIntegration(forMethod ReturnsForMethod)
func (*TestDouble) Spy ¶
func (d *TestDouble) Spy(methodName string) (spy SpyMethodCall)
Spy records all calls to methodName.
Setup Phase ¶
Configure ReturnValues.
Calling Spy twice for the same method will return the same Value (ie there is only every one spy, and it will record methods that do not match any preceding Stub or Mock calls)
Exercise Phase ¶
Matches and records all invocations.
Verify Phase ¶
Can be called again to retrieve the spy for the method (eg to get a dynamically created default Spy).
Extract subsets of RecordedCalls and then verify an Expectations on the number of calls in the subset.
func (*TestDouble) String ¶
func (d *TestDouble) String() string
func (*TestDouble) Stub ¶
func (d *TestDouble) Stub(methodName string) (stub StubbedMethodCall)
Stub adds and returns a StubbedMethodCall for methodName on TestDouble d
Setup phase ¶
Configure Matcher and ReturnValues.
By default a StubbedMethodCall matches any arguments and returns zero values for all outputs.
Exercise Phase ¶
The first stub matching the invocation arguments will provide the output values.
Verify Phase ¶
Nothing to verify
func (*TestDouble) T ¶
func (d *TestDouble) T() T
func (*TestDouble) Verify ¶
func (d *TestDouble) Verify()
type Timewarp ¶ added in v0.0.2
A Timewarp can be used to simulate a sleep, eg when testing using a fake clock. The canonical sleeper is
time.After
type ValidatingReturnValues ¶
type ValidatingReturnValues interface { ReturnValues ForMethod(t T, method reflect.Method) }
type Verifiable ¶
type Verifiable interface {
Verify()
}