generated from dogmatiq/template-go
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathoptional_test.go
172 lines (157 loc) · 3.83 KB
/
optional_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
package imbue_test
import (
"context"
"errors"
"github.com/dogmatiq/imbue"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var _ = Describe("type Optional", func() {
var container *imbue.Container
BeforeEach(func() {
container = imbue.New()
})
AfterEach(func() {
container.Close()
})
It("enables the container to construct values of the declared type", func() {
imbue.With0(
container,
func(ctx imbue.Context) (Concrete1, error) {
return "<concrete>", nil
},
)
imbue.Invoke1(
context.Background(),
container,
func(
ctx context.Context,
dep imbue.Optional[Concrete1],
) error {
v, err := dep.Value()
Expect(err).ShouldNot(HaveOccurred())
Expect(v).To(Equal(Concrete1("<concrete>")))
return nil
},
)
})
It("treats the dependency as unavailable if no constructor is declared", func() {
imbue.Invoke1(
context.Background(),
container,
func(
ctx context.Context,
dep imbue.Optional[Concrete1],
) error {
_, err := dep.Value()
Expect(err).To(MatchError("no constructor is declared for imbue_test.Concrete1"))
return nil
},
)
})
It("treats the dependency as unavailable if its constructor returns an error", func() {
imbue.With0(
container,
func(ctx imbue.Context) (Concrete1, error) {
return "", errors.New("<error>")
},
)
imbue.Invoke1(
context.Background(),
container,
func(
ctx context.Context,
dep imbue.Optional[Concrete1],
) error {
_, err := dep.Value()
Expect(err).Should(HaveOccurred())
Expect(err.Error()).To(MatchRegexp(
`imbue_test\.Concrete1 constructor \(optional_test\.go:\d+\) failed: <error>`,
))
return nil
},
)
})
It("panics when a cyclic dependency is introduced within a single declaration", func() {
Expect(func() {
imbue.With1(
container,
func(
ctx imbue.Context,
dep imbue.Optional[Concrete1],
) (Concrete1, error) {
panic("unexpected call")
},
)
}).To(
PanicWith(
MatchRegexp(
`imbue_test\.Concrete1 constructor \(optional_test\.go:\d+\) depends on itself`,
),
),
)
})
It("panics when a cyclic dependency is introduced across multiple declarations", func() {
imbue.With1(
container,
func(
ctx imbue.Context,
dep Concrete3,
) (Concrete1, error) {
panic("unexpected call")
},
)
imbue.With1(
container,
func(
ctx imbue.Context,
dep imbue.Optional[Concrete1],
) (Concrete2, error) {
panic("unexpected call")
},
)
Expect(func() {
imbue.With1(
container,
func(
ctx imbue.Context,
dep Concrete2,
) (Concrete3, error) {
panic("unexpected call")
},
)
}).To(
PanicWith(
MatchRegexp(
`imbue_test\.Concrete3 constructor \(optional_test\.go:\d+\) introduces a cyclic dependency:` +
`\n\t-> imbue_test\.Concrete2 \(optional_test\.go:\d+\)` +
`\n\t-> imbue_test\.Concrete1 \(optional_test\.go:\d+\)` +
`\n\t-> imbue_test\.Concrete3 \(optional_test\.go:\d+\)`,
),
),
)
})
It("panics if a constructor is declared for an optional type", func() {
Expect(func() {
imbue.With0(
container,
func(
ctx imbue.Context,
) (imbue.Optional[Concrete1], error) {
panic("unexpected call")
},
)
}).To(
PanicWith(
MatchRegexp(
`explicit declaration of imbue\.Optional\[(imbue|github.com\/dogmatiq\/imbue_test)\.Concrete1\] constructor \(optional_test\.go:\d+\) is disallowed`,
// ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// | |
// Go v1.18 shows the wrong package name ----' |
// |
// Go 1.19 gets the name right, but adds the path -------------'
),
),
)
})
})