-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathintrospector_test.go
236 lines (212 loc) · 7.04 KB
/
introspector_test.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
package introspector_test
import (
"errors"
"net/url"
"reflect"
"testing"
"github.com/infinytum/injector"
"github.com/infinytum/introspector"
)
type TestFactoryFunc func(int) reflect.Value
type TestResult struct {
introspector.IntrospectorResult[TestFactoryFunc]
}
type InvalidTestResult struct {
}
func (i InvalidTestResult) FactoryMap() map[int]TestFactoryFunc {
return nil
}
func (i InvalidTestResult) Type() reflect.Type {
return nil
}
// Write a test that verifies that NewIntrospector returns an instance of the Introspector interface.
//
// The test should:
// - call the NewIntrospector function
// - verify that the returned value is an instance of the Introspector interface
func TestNewIntrospector(t *testing.T) {
i, err := introspector.NewIntrospector[TestFactoryFunc, TestResult]()
if err != nil {
t.Fatal(err)
}
if i == nil {
t.Fatal("expected introspector to be not nil")
}
}
// Write a test that verifies that NewIntrospector returns an error if the result type does not implement the IntrospectorResult interface correctly.
//
// The test should:
// - call the NewIntrospector function with a result type that does not implement the IntrospectorResult interface
// - verify that the returned error is not nil
func TestNewIntrospectorInvalidResultType(t *testing.T) {
_, err := introspector.NewIntrospector[TestFactoryFunc, InvalidTestResult]()
if err == nil {
t.Fatal("expected error to be not nil")
}
}
// Write a test that verifies that FactoryMap is not nil after calling NewIntrospector.
//
// The test should:
// - call the NewIntrospector function
// - verify that the FactoryMap method of the returned value is not nil
func TestFactoryMapNotNil(t *testing.T) {
i, err := introspector.NewIntrospector[TestFactoryFunc, TestResult]()
if err != nil {
t.Fatal(err)
}
if i.FactoryMap() == nil {
t.Fatal("expected factory map to be not nil")
}
}
// Write a test that verifies that the RegisterFactory function works as expected.
//
// The test should:
// - create an instance of the Introspector interface
// - call the RegisterFactory function with a factory function and the Introspector instance
// - verify that the factory function is registered on the Introspector instance
func TestRegisterFactory(t *testing.T) {
i, err := introspector.NewIntrospector[TestFactoryFunc, TestResult]()
if err != nil {
t.Fatal(err)
}
introspector.RegisterFactory[int](func(i int) reflect.Value {
return reflect.ValueOf(i * 2)
}, i)
if len(i.FactoryMap()) != 1 {
t.Fatal("expected factory map to have one entry")
}
factory, ok := i.FactoryMap()[reflect.TypeOf(int(1))]
if !ok {
t.Fatal("expected factory map to have entry for type int")
}
if factory(1).Interface().(int) != 2 {
t.Fatal("expected factory to return 2")
}
}
// Write a test that verifies that the SetDefaultFactory function works as expected.
//
// The test should:
// - create an instance of the Introspector interface
// - call the SetDefaultFactory function with a default factory function and the Introspector instance
// - verify that the default factory function is registered on the Introspector instance
func TestSetDefaultFactory(t *testing.T) {
i, err := introspector.NewIntrospector[TestFactoryFunc, TestResult]()
if err != nil {
t.Fatal(err)
}
u := url.URL{}
injector.Singleton(func() url.URL {
return u
})
i.SetDefaultFactory(func(r reflect.Type) (TestFactoryFunc, error) {
val, err := introspector.InjectorFactoryFunc(r)
return func(i int) reflect.Value {
return *val
}, err
})
if len(i.FactoryMap()) != 0 {
t.Fatal("expected factory map to have zero entry")
}
res, errs := i.Introspect(func(i url.URL) {})
if len(errs) != 0 {
t.Fatal(err)
}
if len(res.FactoryMap()) != 1 {
t.Fatal("expected result factory map to have one entry")
}
factory, ok := res.FactoryMap()[0]
if !ok {
t.Fatal("expected factory map to have entry for arg 0")
}
if factory(1).Interface().(url.URL) != u {
t.Fatal("expected factory to return same url")
}
}
// Write a test that verifies that the Introspect function works as expected.
//
// The test should:
// - create an instance of the Introspector interface
// - register a factory function on the Introspector instance
// - call the Introspect function with a function and the Introspector instance
// - verify that the Introspect function returns an instance of the IntrospectorResult interface
func TestIntrospect(t *testing.T) {
i, err := introspector.NewIntrospector[TestFactoryFunc, TestResult]()
if err != nil {
t.Fatal(err)
}
introspector.RegisterFactory[int](func(i int) reflect.Value {
return reflect.ValueOf(i * 2)
}, i)
res, errs := i.Introspect(func(i int) {})
if len(errs) != 0 {
t.Fatal(errs)
}
if res == nil {
t.Fatal("expected result to be not nil")
}
if len(res.FactoryMap()) != 1 {
t.Fatal("expected result factory map to have one entry")
}
if res.Type() != reflect.TypeOf(func(i int) {}) {
t.Fatal("expected result type to be func(i int)")
}
factory, ok := res.FactoryMap()[0]
if !ok {
t.Fatal("expected factory map to have entry for arg 0")
}
if factory(1).Interface().(int) != 2 {
t.Fatal("expected factory to return 2")
}
}
// Write a test that verifies that the Introspect function returns an error if no factory function is registered for a parameter type.
//
// The test should:
// - create an instance of the Introspector interface
// - call the Introspect function with a function and the Introspector instance
// - verify that the Introspect function returns an error
func TestIntrospectNoFactory(t *testing.T) {
i, err := introspector.NewIntrospector[TestFactoryFunc, TestResult]()
if err != nil {
t.Fatal(err)
}
_, errs := i.Introspect(func(i int) {})
if len(errs) == 0 {
t.Fatal("expected error to be not nil")
}
}
// Write a test that verifies that the Introspect function returns an error if the function has a variadic parameter.
//
// The test should:
// - create an instance of the Introspector interface
// - call the Introspect function with a function that has a variadic parameter
// - verify that the Introspect function returns an error
func TestIntrospectVariadic(t *testing.T) {
i, err := introspector.NewIntrospector[TestFactoryFunc, TestResult]()
if err != nil {
t.Fatal(err)
}
_, errs := i.Introspect(func(i ...int) {})
if len(errs) == 0 {
t.Fatal("expected error to be not nil")
}
}
// Write a test that verifies that the Introspect function returns an error if the default factory function returns an error.
//
// The test should:
// - create an instance of the Introspector interface
// - call the SetDefaultFactory function with a default factory function that returns an error
// - call the Introspect function with a function
// - verify that the Introspect function returns an error
func TestIntrospectDefaultFactoryError(t *testing.T) {
i, err := introspector.NewIntrospector[TestFactoryFunc, TestResult]()
if err != nil {
t.Fatal(err)
}
i.SetDefaultFactory(func(r reflect.Type) (TestFactoryFunc, error) {
return nil, errors.New("test error")
})
_, errs := i.Introspect(func(i int) {})
if len(errs) == 0 {
t.Fatal("expected error to be not nil")
}
}