@@ -7,28 +7,33 @@ import (
7
7
"io"
8
8
"log"
9
9
"os"
10
- "os/exec"
11
10
"path/filepath"
12
11
"specmatic-order-bff-grpc-go/internal/com/store/order/bff/config"
13
12
"strconv"
14
13
"testing"
14
+ "time"
15
15
16
16
"github.com/docker/go-connections/nat"
17
+ "github.com/stretchr/testify/require"
17
18
"github.com/testcontainers/testcontainers-go"
19
+ "github.com/testcontainers/testcontainers-go/network"
18
20
"github.com/testcontainers/testcontainers-go/wait"
19
21
)
20
22
21
23
type testEnvironment struct {
22
24
ctx context.Context
23
25
domainServiceContainer testcontainers.Container
24
26
domainServiceDynamicPort string
27
+ kafkaServiceContainer testcontainers.Container
28
+ kafkaServiceDynamicPort string
25
29
bffServiceContainer testcontainers.Container
26
30
bffServiceDynamicPort string
31
+ dockerNetwork * testcontainers.DockerNetwork
27
32
config * config.Config
28
33
}
29
34
30
- func TestIntegration (t * testing.T ) {
31
- env := setUpEnv (t )
35
+ func TestContract (t * testing.T ) {
36
+ env := setUpEnv (t )
32
37
33
38
// setUp (start domain service stub with specmatic-grpc and bff server in container)
34
39
setUp (t , env )
@@ -41,35 +46,51 @@ func TestIntegration(t *testing.T) {
41
46
}
42
47
43
48
func setUpEnv (t * testing.T ) * testEnvironment {
44
- config , err := config .LoadConfig ("config.yaml" )
45
- if err != nil {
46
- t .Fatalf ("Failed to load config: %v" , err )
47
- }
48
-
49
- return & testEnvironment {
50
- ctx : context .Background (),
51
- config : config ,
52
- }
49
+ config , err := config .LoadConfig ()
50
+ if err != nil {
51
+ t .Fatalf ("Failed to load config: %v" , err )
52
+ }
53
+
54
+ return & testEnvironment {
55
+ ctx : context .Background (),
56
+ config : config ,
57
+ }
53
58
}
54
59
55
60
func setUp (t * testing.T , env * testEnvironment ) {
56
61
var err error
57
62
63
+ // Create a sub net and store in env.
64
+ newNetwork , err := network .New (env .ctx )
65
+ if err != nil {
66
+ t .Fatal (err )
67
+ }
68
+ t .Cleanup (func () {
69
+ require .NoError (t , newNetwork .Remove (env .ctx ))
70
+ })
71
+ env .dockerNetwork = newNetwork
72
+
58
73
printHeader (t , 1 , "Starting Domain Service" )
59
74
env .domainServiceContainer , env .domainServiceDynamicPort , err = startDomainService (env )
60
75
if err != nil {
61
- t .Fatalf ("could not start domain service container: %v" , err )
76
+ t .Fatalf ("could not start domain service container: %v" , err )
77
+ }
78
+
79
+ printHeader (t , 2 , "Starting Kafka Service" )
80
+ env .kafkaServiceContainer , env .kafkaServiceDynamicPort , err = startKafkaMock (env )
81
+ if err != nil {
82
+ t .Fatalf ("could not start domain service container: %v" , err )
62
83
}
63
84
64
- printHeader (t , 2 , "Starting BFF Service" )
85
+ printHeader (t , 3 , "Starting BFF Service" )
65
86
env .bffServiceContainer , env .bffServiceDynamicPort , err = startBFFService (t , env )
66
87
if err != nil {
67
- t .Fatalf ("could not start bff service container: %v" , err )
88
+ t .Fatalf ("could not start bff service container: %v" , err )
68
89
}
69
90
}
70
91
71
92
func runTests (t * testing.T , env * testEnvironment ) {
72
- printHeader (t , 3 , "Starting tests" )
93
+ printHeader (t , 4 , "Starting tests" )
73
94
testLogs , err := runTestContainer (env )
74
95
if err != nil {
75
96
t .Fatalf ("Could not run test container: %s" , err )
@@ -86,6 +107,11 @@ func tearDown(t *testing.T, env *testEnvironment) {
86
107
t .Logf ("Failed to terminate BFF container: %v" , err )
87
108
}
88
109
}
110
+ if env .kafkaServiceContainer != nil {
111
+ if err := env .kafkaServiceContainer .Terminate (env .ctx ); err != nil {
112
+ t .Logf ("Failed to terminate Kafka container: %v" , err )
113
+ }
114
+ }
89
115
if env .domainServiceContainer != nil {
90
116
if err := env .domainServiceContainer .Terminate (env .ctx ); err != nil {
91
117
t .Logf ("Failed to terminate stub container: %v" , err )
@@ -111,6 +137,12 @@ func startDomainService(env *testEnvironment) (testcontainers.Container, string,
111
137
Mounts : testcontainers .Mounts (
112
138
testcontainers .BindMount (filepath .Join (pwd , "specmatic.yaml" ), "/usr/src/app/specmatic.yaml" ),
113
139
),
140
+ Networks : []string {
141
+ env .dockerNetwork .Name ,
142
+ },
143
+ NetworkAliases : map [string ][]string {
144
+ env .dockerNetwork .Name : {"order-api-mock" },
145
+ },
114
146
WaitingFor : wait .ForLog ("Stub server is running" ),
115
147
}
116
148
@@ -130,33 +162,86 @@ func startDomainService(env *testEnvironment) (testcontainers.Container, string,
130
162
return stubContainer , domainServicePort .Port (), nil
131
163
}
132
164
133
- func startBFFService (t * testing.T , env * testEnvironment ) (testcontainers.Container , string , error ) {
134
- dockerfilePath := "Dockerfile"
165
+ func startKafkaMock (env * testEnvironment ) (testcontainers.Container , string , error ) {
166
+ pwd , err := os .Getwd ()
167
+ if err != nil {
168
+ return nil , "" , fmt .Errorf ("Error getting current directory: %v" , err )
135
169
136
- bffImageName := "specmatic-order-bff-grpc-go"
137
- buildCmd := exec .Command ("docker" , "build" , "-t" , bffImageName , "-f" , dockerfilePath , "." )
170
+ }
138
171
139
- if err := buildCmd .Run (); err != nil {
140
- return nil , "" , fmt .Errorf ("could not build BFF image: %w" , err )
172
+ port , err := nat .NewPort ("tcp" , env .config .KafkaService .Port )
173
+ if err != nil {
174
+ return nil , "" , fmt .Errorf ("invalid port number: %w" , err )
141
175
}
142
176
177
+ req := testcontainers.ContainerRequest {
178
+ Name : "specmatic-kafka" ,
179
+ Image : "znsio/specmatic-kafka-trial:0.22.5" ,
180
+ ExposedPorts : []string {port .Port () + "/tcp" },
181
+ Networks : []string {
182
+ env .dockerNetwork .Name ,
183
+ },
184
+ NetworkAliases : map [string ][]string {
185
+ env .dockerNetwork .Name : {"specmatic-kafka" },
186
+ },
187
+ Env : map [string ]string {
188
+ "KAFKA_EXTERNAL_HOST" : env .config .KafkaService .Host ,
189
+ "KAFKA_EXTERNAL_PORT" : port .Port (),
190
+ },
191
+ Cmd : []string {"--config=/specmatic.json" }, // TODO: Switch to YAML
192
+ Mounts : testcontainers .Mounts (
193
+ testcontainers .BindMount (filepath .Join (pwd , "specmatic.json" ), "/specmatic.json" ),
194
+ ),
195
+ WaitingFor : wait .ForLog ("Listening on topics: (product-queries)" ).WithStartupTimeout (2 * time .Minute ),
196
+ }
197
+
198
+ kafkaC , err := testcontainers .GenericContainer (env .ctx , testcontainers.GenericContainerRequest {
199
+ ContainerRequest : req ,
200
+ Started : true ,
201
+ })
202
+ if err != nil {
203
+ fmt .Printf ("Error starting Kafka mock container: %v" , err )
204
+ }
205
+
206
+ mappedPort , err := kafkaC .MappedPort (env .ctx , port )
207
+ if err != nil {
208
+ fmt .Printf ("Error getting mapped port for Kafka mock: %v" , err )
209
+ }
210
+
211
+ return kafkaC , mappedPort .Port (), nil
212
+ }
213
+
214
+ func startBFFService (t * testing.T , env * testEnvironment ) (testcontainers.Container , string , error ) {
215
+
143
216
port , err := nat .NewPort ("tcp" , env .config .BFFServer .Port )
144
217
if err != nil {
145
218
return nil , "" , fmt .Errorf ("invalid port number: %w" , err )
146
219
}
147
220
221
+ dockerfilePath := "Dockerfile"
222
+ contextPath := "."
223
+
148
224
req := testcontainers.ContainerRequest {
149
- Image : bffImageName ,
225
+ FromDockerfile : testcontainers.FromDockerfile {
226
+ Context : contextPath ,
227
+ Dockerfile : dockerfilePath ,
228
+ },
150
229
Env : map [string ]string {
151
- "DOMAIN_SERVER_PORT" : env .domainServiceDynamicPort ,
152
- "DOMAIN_SERVER_HOST" : "host.docker.internal" ,
230
+ "DOMAIN_SERVER_PORT" : env .config .Backend .Port ,
231
+ "DOMAIN_SERVER_HOST" : "order-api-mock" ,
232
+ "KAFKA_PORT" : env .config .KafkaService .Port ,
233
+ "KAFKA_HOST" : "specmatic-kafka" ,
153
234
},
154
- ExposedPorts : []string {port .Port () + "/tcp" },
235
+ Networks : []string {
236
+ env .dockerNetwork .Name ,
237
+ },
238
+ NetworkAliases : map [string ][]string {
239
+ env .dockerNetwork .Name : {"bff-service" },
240
+ },
241
+ ExposedPorts : []string {env .config .BFFServer .Port + "/tcp" },
155
242
WaitingFor : wait .ForLog ("Starting gRPC server" ),
156
243
}
157
244
158
- t .Log ("Container created" )
159
-
160
245
bffContainer , err := testcontainers .GenericContainer (env .ctx , testcontainers.GenericContainerRequest {
161
246
ContainerRequest : req ,
162
247
Started : true ,
@@ -179,7 +264,8 @@ func runTestContainer(env *testEnvironment) (string, error) {
179
264
log .Fatalf ("Error getting current directory: %v" , err )
180
265
}
181
266
182
- bffPortInt , err := strconv .Atoi (env .bffServiceDynamicPort )
267
+ bffPortInt , err := strconv .Atoi (env .config .BFFServer .Port )
268
+ // bffPortInt, err := strconv.Atoi(env.bffServiceDynamicPort)
183
269
if err != nil {
184
270
return "" , fmt .Errorf ("invalid port number: %w" , err )
185
271
}
@@ -189,10 +275,13 @@ func runTestContainer(env *testEnvironment) (string, error) {
189
275
Env : map [string ]string {
190
276
"SPECMATIC_GENERATIVE_TESTS" : "true" ,
191
277
},
192
- Cmd : []string {"test" , fmt .Sprintf ("--port=%d" , bffPortInt ), "--host=host.docker.internal " },
278
+ Cmd : []string {"test" , fmt .Sprintf ("--port=%d" , bffPortInt ), "--host=bff-service " },
193
279
Mounts : testcontainers .Mounts (
194
280
testcontainers .BindMount (filepath .Join (pwd , "specmatic.yaml" ), "/usr/src/app/specmatic.yaml" ),
195
281
),
282
+ Networks : []string {
283
+ env .dockerNetwork .Name ,
284
+ },
196
285
WaitingFor : wait .ForLog ("Passed Tests:" ),
197
286
}
198
287
0 commit comments