-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathregistrars_placeholder_test.go
161 lines (124 loc) · 5.27 KB
/
registrars_placeholder_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
package ore
import (
"context"
"testing"
m "github.com/firasdarwish/ore/internal/models"
"github.com/firasdarwish/ore/internal/testtools/assert2"
"github.com/stretchr/testify/assert"
)
func TestPlaceholder_HappyPath(t *testing.T) {
clearAll()
//register a placeholder
RegisterPlaceholder[*m.Trader]()
//get the placeholder value would fail
assert2.PanicsWithError(t, assert2.ErrorStartsWith("no value has been provided for this placeholder"), func() {
_, _ = Get[*m.Trader](context.Background())
})
//get list would return empty
traders, _ := GetList[*m.Trader](context.Background())
assert.Empty(t, traders)
//provide a value to the placeholder
ctx := ProvideScopedValue[*m.Trader](context.Background(), &m.Trader{Name: "Peter"})
//get the placeholder value would success
trader, _ := Get[*m.Trader](ctx)
assert.Equal(t, "Peter", trader.Name)
//get list will include the placeholder value
traders, ctx = GetList[*m.Trader](ctx)
assert.Equal(t, 1, len(traders))
//Register alias to the placeholder
RegisterAlias[m.IPerson, *m.Trader]()
//get the alias value would success
person, ctx := Get[m.IPerson](ctx)
assert.Equal(t, "Peter", person.(*m.Trader).Name)
//get list will include the placeholder value
persons, _ := GetList[m.IPerson](ctx)
assert.Equal(t, 1, len(persons))
}
func TestPlaceholder_ProvideValueBeforeRegistering(t *testing.T) {
clearAll()
//provide a value to the placeholder
ctx := ProvideScopedValue[*m.Trader](context.Background(), &m.Trader{Name: "Mary"})
//get the placeholder value would fail because no placeholder has been registered
assert2.PanicsWithError(t, assert2.ErrorStartsWith("implementation not found for type"), func() {
_, _ = Get[*m.Trader](ctx)
})
//register a matching placeholder
RegisterPlaceholder[*m.Trader]()
//get the placeholder value would success
trader, _ := Get[*m.Trader](ctx)
assert.Equal(t, "Mary", trader.Name)
}
// can not register a placeholder to override a real resolver
func TestPlaceholder_OverrideRealResolver(t *testing.T) {
clearAll()
//register a real resolver
RegisterKeyedSingleton(&m.Trader{Name: "Mary"}, "module1")
//register a placeholder to override the real resolver should fail
assert2.PanicsWithError(t, assert2.ErrorContains("has already been registered"), func() {
RegisterKeyedPlaceholder[*m.Trader]("module1")
})
//register 2 time a placeholder should fail
RegisterKeyedPlaceholder[*m.Trader]("module2")
assert2.PanicsWithError(t, assert2.ErrorContains("has already been registered"), func() {
RegisterKeyedPlaceholder[*m.Trader]("module2")
})
}
func TestPlaceholder_OverridePlaceholder(t *testing.T) {
clearAll()
//register a placeholder
RegisterKeyedPlaceholder[*m.Trader]("module2")
//Provide the value to the placeholder
ctx := ProvideKeyedScopedValue[*m.Trader](context.Background(), &m.Trader{Name: "John"}, "module2")
//get the placeholder value would success
trader, ctx := GetKeyed[*m.Trader](ctx, "module2")
assert.Equal(t, "John", trader.Name)
//replace the placeholder value "John" with a new value "David"
ctx = ProvideKeyedScopedValue[*m.Trader](ctx, &m.Trader{Name: "David"}, "module2")
trader, ctx = GetKeyed[*m.Trader](ctx, "module2")
assert.Equal(t, "David", trader.Name)
traders, ctx := GetKeyedList[*m.Trader](ctx, "module2")
assert.Equal(t, 1, len(traders))
assert.Equal(t, "David", traders[0].Name)
//Register a real resolver should override the placeholder resolver
RegisterKeyedFunc(Singleton, func(ctx context.Context) (*m.Trader, context.Context) {
return &m.Trader{Name: "Mary"}, ctx
}, "module2")
trader, ctx = GetKeyed[*m.Trader](ctx, "module2")
assert.Equal(t, "Mary", trader.Name)
//Get both the placeholder value ("David") and the real resolver value ("Mary")
traders, ctx = GetKeyedList[*m.Trader](ctx, "module2")
assert.Equal(t, 2, len(traders)) //David and Mary
assert.True(t, tradersListContainsName(traders, "David"))
assert.True(t, tradersListContainsName(traders, "Mary"))
//replace the placeholder value ("David") with a new value ("Nathan")
ctx = ProvideKeyedScopedValue[*m.Trader](ctx, &m.Trader{Name: "Nathan"}, "module2")
//the placeholder value cannot override the real resolver value
trader, ctx = GetKeyed[*m.Trader](ctx, "module2")
assert.Equal(t, "Mary", trader.Name)
//but it replaces the old placeholder value ("Nathan" will replace "David")
traders, _ = GetKeyedList[*m.Trader](ctx, "module2")
assert.Equal(t, 2, len(traders)) //Nathan and Mary
assert.True(t, tradersListContainsName(traders, "Nathan"))
assert.True(t, tradersListContainsName(traders, "Mary"))
}
// placeholder value of a module is not accessible from other module
func TestPlaceholder_PerModule(t *testing.T) {
con1 := NewContainer()
RegisterPlaceholderToContainer[*m.Trader](con1)
con2 := NewContainer()
RegisterPlaceholderToContainer[*m.Trader](con2)
ctx := ProvideScopedValueToContainer(con1, context.Background(), &m.Trader{Name: "John"})
trader, ctx := GetFromContainer[*m.Trader](con1, ctx)
assert.Equal(t, "John", trader.Name)
assert2.PanicsWithError(t, assert2.ErrorStartsWith("no value has been provided for this placeholder"), func() {
trader, ctx = GetFromContainer[*m.Trader](con2, ctx)
})
}
func tradersListContainsName(p []*m.Trader, name string) bool {
for _, v := range p {
if v.Name == name {
return true
}
}
return false
}