@@ -3,50 +3,27 @@ package atesting
3
3
4
4
import (
5
5
"container/list"
6
+ . "github.com/go-autowire/autowire"
7
+ "github.com/go-autowire/autowire/internal"
6
8
"log"
7
9
"reflect"
8
- "unicode"
9
-
10
- "github.com/go-autowire/autowire"
11
10
)
12
11
13
- // Spy Function is replacing object field with the one provided in the function as a second argument.
14
- // Spy Function detects automatically which field could be replaced with the provided one.
15
- // Important note: In order to traverse fields of the unexported fields we need to implement Getters.
16
- // As shown inside example package, we are replacing AuditClient with our mock implementation and in order to reach this
17
- // field we need Getter.
12
+ // Spy Function is replacing object field with the one provided in the function as a variadic arguments.
13
+ // Spy Function will detect fully automatically which field could be replaced
14
+ // with the provided one as variadic arguments.
15
+ // As shown inside example package, we are replacing AuditClient with our mock implementation.
18
16
// Example:
19
- // atesting. Spy(application, &TestAuditClient{})
20
- // Or this is equivalent of
17
+ // Spy(application, &TestAuditClient{})
18
+ // Or this is equivalent of doing it manually
21
19
// application.UserSvc().SetAuditClient(&TestAuditClient{})
22
- // Getter UserSvc() is used to access userSvc field, which is unexported.
23
- // For more information take a look at example package.
20
+ // When we don't use Spy function, we need to provide Getter method UserSvc() in order to
21
+ // access unexported userSvc field.
22
+ // For more information take a look at test file in example package.
24
23
// Parameters of Spy function:
25
- // - `v` : pointer to structure inside which spy object will be applied
26
- // - `dependency` : pointer to structure which will be injected
27
- func Spy (v interface {}, dependency interface {}) {
28
- slice := []interface {}{dependency }
29
- Spies (v , slice )
30
- }
31
-
32
- // Spies Function is replacing object fields with the list of provided dependencies
33
- // in the function as a second argument. Spy Function detects automatically which field
34
- // could be replaced with the provided one in the list of dependencies.
35
- // Important note: In order to traverse fields of the unexported fields we need to implement Getters.
36
- // As shown inside example package, we are replacing AuditClient with our mock implementation and in order to reach this
37
- // field we need Getter.
38
- // Example:
39
- // atesting.Spies(application, []interface{}{&TestPaymentServiceTest{}, &TestAuditClient{}})
40
- // Or this is equivalent of
41
- // application.UserSvc().SetAuditClient(&TestAuditClient{})
42
- // application.UserSvc().PaymentSvc = &TestPaymentServiceTest{}
43
- // Getter UserSvc() is used to access userSvc field, which is unexported. In case of PaymentSvc it is not required
44
- // as field PaymentSvc is exported.
45
- // Parameters of Spies function:
46
- // - `v` : structure inside which spy objects will be applied
47
- // - `dependencies` : list of dependencies which will be injected
48
- // For more information take a look at example package.
49
- func Spies (v interface {}, dependencies []interface {}) {
24
+ // - `v` : pointer to structure inside which spy object will be injected
25
+ // - `dependencies` : this is variadic argument, pointer to mocked structures which are gonna be injected
26
+ func Spy (v interface {}, dependencies ... interface {}) {
50
27
queue := list .New ()
51
28
queue .PushBack (v )
52
29
for queue .Len () > 0 {
@@ -57,56 +34,37 @@ func Spies(v interface{}, dependencies []interface{}) {
57
34
switch value .Kind () {
58
35
case reflect .Ptr :
59
36
elem = value .Elem ()
60
- case reflect .Struct :
61
- elem = value
62
37
}
63
38
for i := 0 ; i < elem .NumField (); i ++ {
64
39
field := elem .Type ().Field (i )
65
- tag , ok := field .Tag .Lookup (autowire . Tag )
40
+ tag , ok := field .Tag .Lookup (Tag )
66
41
if ok {
67
42
if tag != "" {
68
- for _ , dependency := range dependencies {
69
- dependValue := reflect .ValueOf (dependency )
43
+ for _ , currentDependency := range dependencies {
44
+ dependValue := reflect .ValueOf (currentDependency )
70
45
if dependValue .Type ().Implements (field .Type ) {
71
46
t := reflect .New (dependValue .Type ())
72
- log .Println ("Injecting Spy on dependency by tag " + tag + " will be used " + t .Type ().String ())
73
- autowire .Autowire (dependency )
74
- setFieldValue (value , elem , i , dependency )
47
+ log .Println ("Injecting Spy on currentDependency by tag " + tag + " will be used " + t .Type ().String ())
48
+ Autowire (currentDependency )
49
+ internal .SetFieldValue (elem , i , currentDependency )
50
+ }
51
+ }
52
+ } else {
53
+ for _ , currentDependency := range dependencies {
54
+ log .Printf ("Checking compatability between %s & %s" , reflect .TypeOf (currentDependency ), elem .Field (i ).Type ())
55
+ if reflect .TypeOf (currentDependency ) == elem .Field (i ).Type () {
56
+ internal .SetFieldValue (elem , i , currentDependency )
75
57
}
76
58
}
77
59
}
78
60
if ! elem .Field (i ).IsNil () {
79
61
if elem .Field (i ).Elem ().CanInterface () {
80
- queue .PushBack (autowire . Autowired (elem .Field (i ).Elem ().Interface ()))
62
+ queue .PushBack (Autowired (elem .Field (i ).Elem ().Interface ()))
81
63
} else {
82
- runeName := []rune (elem .Type ().Field (i ).Name )
83
- runeName [0 ] = unicode .ToUpper (runeName [0 ])
84
- methodName := string (runeName )
85
- method := value .MethodByName (methodName )
86
- if method .IsValid () {
87
- result := method .Call ([]reflect.Value {})[0 ]
88
- queue .PushBack (autowire .Autowired (result .Interface ()))
89
- }
64
+ queue .PushBack (Autowired (internal .GetUnexportedField (elem .Field (i ))))
90
65
}
91
66
}
92
67
}
93
68
}
94
69
}
95
70
}
96
-
97
- func setFieldValue (value reflect.Value , elem reflect.Value , i int , dependency interface {}) bool {
98
- runeName := []rune (elem .Type ().Field (i ).Name )
99
- exported := unicode .IsUpper (runeName [0 ])
100
- if exported {
101
- elem .Field (i ).Set (reflect .ValueOf (dependency ))
102
- } else {
103
- runeName [0 ] = unicode .ToUpper (runeName [0 ])
104
- methodName := "Set" + string (runeName )
105
- method := value .MethodByName (methodName )
106
- if method .IsValid () {
107
- method .Call ([]reflect.Value {reflect .ValueOf (dependency )})
108
- return true
109
- }
110
- }
111
- return false
112
- }
0 commit comments