-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdouble.go
97 lines (83 loc) · 3.05 KB
/
double.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package moka
import (
"errors"
"fmt"
"reflect"
)
// Double is the interface implemented by all Moka double types.
type Double interface {
addInteraction(interaction interaction)
Call(methodName string, args ...interface{}) ([]interface{}, error)
verifyInteractions()
}
// StrictDouble is a strict implementation of the Double interface.
// Any invocation of the `Call` method that won't match any of the configured
// interactions will trigger a test failure and return an error.
type StrictDouble struct {
interactions []interaction
interactionValidator interactionValidator
failHandler FailHandler
}
// NewStrictDouble instantiates a new `StrictDouble`, using the global fail
// handler and no validation on the configured interactions.
func NewStrictDouble() *StrictDouble {
return newStrictDoubleWithInteractionValidatorAndFailHandler(
newNullInteractionValidator(),
globalFailHandler,
)
}
// NewStrictDoubleWithTypeOf instantiates a new `StrictDouble`, using the
// global fail handler and validating that any configured interaction matches
// the specified type.
func NewStrictDoubleWithTypeOf(value interface{}) *StrictDouble {
return newStrictDoubleWithInteractionValidatorAndFailHandler(
newTypeInteractionValidator(reflect.TypeOf(value)),
globalFailHandler,
)
}
func newStrictDoubleWithInteractionValidatorAndFailHandler(interactionValidator interactionValidator, failHandler FailHandler) *StrictDouble {
if failHandler == nil {
panic("You are trying to instantiate a double, but Moka's fail handler is nil.\n" +
"If you're using Ginkgo, make sure you instantiate your doubles in a BeforeEach(), JustBeforeEach() or It() block.\n" +
"Alternatively, you may have forgotten to register a fail handler with RegisterDoublesFailHandler().")
}
return &StrictDouble{
interactions: []interaction{},
interactionValidator: interactionValidator,
failHandler: failHandler,
}
}
// Call performs a method call on the double. If a matching interaction is
// found, its return values will be returned. If no configured interaction
// matches, an error will be returned.
func (d *StrictDouble) Call(methodName string, args ...interface{}) ([]interface{}, error) {
for _, interaction := range d.interactions {
interactionReturnValues, interactionMatches := interaction.call(methodName, args)
if interactionMatches {
return interactionReturnValues, nil
}
}
errorMessage := fmt.Sprintf("Unexpected interaction: %s", formatMethodCall(methodName, args))
d.fail(errorMessage)
return nil, errors.New(errorMessage)
}
func (d *StrictDouble) addInteraction(interaction interaction) {
validationError := d.interactionValidator.validate(interaction)
if validationError != nil {
d.fail(validationError.Error())
return
}
d.interactions = append(d.interactions, interaction)
}
func (d *StrictDouble) verifyInteractions() {
for _, interaction := range d.interactions {
err := interaction.verify()
if err != nil {
d.fail(err.Error())
return
}
}
}
func (d *StrictDouble) fail(message string) {
d.failHandler(message, 4)
}