@@ -49,7 +49,8 @@ import java.util.Optional
49
49
import java.util.concurrent.ConcurrentHashMap
50
50
import kotlin.reflect.full.findAnnotation
51
51
52
- class PactConsumerTestExt : Extension , BeforeTestExecutionCallback , BeforeAllCallback , ParameterResolver , AfterTestExecutionCallback , AfterAllCallback {
52
+ class PactConsumerTestExt : Extension , BeforeTestExecutionCallback , BeforeAllCallback , ParameterResolver ,
53
+ AfterTestExecutionCallback , AfterAllCallback {
53
54
54
55
private val ep: ExpressionParser = ExpressionParser ()
55
56
@@ -131,7 +132,7 @@ class PactConsumerTestExt : Extension, BeforeTestExecutionCallback, BeforeAllCal
131
132
): Any {
132
133
val pact = lookupPact(providerInfo.first, providerInfo.second, extensionContext)
133
134
return if (type.isAssignableFrom(MockServer ::class .java) && mockServerConfigured(extensionContext)) {
134
- setupMockServer (providerInfo.first, providerInfo.second, extensionContext)
135
+ setupMockServerForProvider (providerInfo.first, providerInfo.second, extensionContext)
135
136
} else when (providerInfo.first.providerType) {
136
137
ProviderType .ASYNCH -> when {
137
138
type.isAssignableFrom(List ::class .java) -> pact.interactions
@@ -169,7 +170,8 @@ class PactConsumerTestExt : Extension, BeforeTestExecutionCallback, BeforeAllCal
169
170
else -> throw UnsupportedOperationException (" Could not inject parameter $type into test method" )
170
171
}
171
172
else -> when {
172
- type.isAssignableFrom(MockServer ::class .java) -> setupMockServer(providerInfo.first, providerInfo.second, extensionContext)
173
+ type.isAssignableFrom(MockServer ::class .java) ->
174
+ setupMockServerForProvider(providerInfo.first, providerInfo.second, extensionContext)
173
175
type.isAssignableFrom(RequestResponsePact ::class .java) -> pact.asRequestResponsePact().unwrap()
174
176
type.isAssignableFrom(V4Pact ::class .java) -> pact.asV4Pact().unwrap()
175
177
type.isAssignableFrom(V4Interaction .SynchronousHttp ::class .java) -> {
@@ -215,20 +217,24 @@ class PactConsumerTestExt : Extension, BeforeTestExecutionCallback, BeforeAllCal
215
217
providerInfo.providerType == null ||
216
218
providerInfo.providerType == ProviderType .SYNCH ||
217
219
providerInfo.providerType == ProviderType .UNSPECIFIED ) {
218
- val mockServer = setupMockServer (providerInfo, pactMethod, context)
220
+ val mockServer = setupMockServerForProvider (providerInfo, pactMethod, context)
219
221
mockServer.start()
220
222
mockServer.waitForServer()
221
223
}
222
224
}
223
225
}
224
226
225
- private fun setupMockServer (providerInfo : ProviderInfo , pactMethod : String , context : ExtensionContext ): AbstractBaseMockServer {
227
+ private fun setupMockServerForProvider (
228
+ providerInfo : ProviderInfo ,
229
+ pactMethod : String ,
230
+ context : ExtensionContext
231
+ ): AbstractBaseMockServer {
226
232
val store = context.getStore(NAMESPACE )
227
233
val key = " mockServer:${providerInfo.providerName} "
228
234
return when {
229
235
store[key] != null -> store[key] as AbstractBaseMockServer
230
236
else -> {
231
- val config = mockServerConfigFromAnnotation(context).merge(providerInfo.mockServerConfig())
237
+ val config = mockServerConfigFromAnnotation(context, providerInfo ).merge(providerInfo.mockServerConfig())
232
238
store.put(" mockServerConfig:${providerInfo.providerName} " , config)
233
239
val mockServer = mockServer(lookupPact(providerInfo, pactMethod, context), config)
234
240
store.put(key, JUnit5MockServerSupport (mockServer))
@@ -240,26 +246,62 @@ class PactConsumerTestExt : Extension, BeforeTestExecutionCallback, BeforeAllCal
240
246
private fun mockServerConfigured (extensionContext : ExtensionContext ): Boolean {
241
247
val mockServerConfig = AnnotationSupport .findAnnotation(extensionContext.requiredTestClass,
242
248
MockServerConfig ::class .java)
243
- val mockServerConfigMethod = AnnotationSupport .findAnnotation (extensionContext.requiredTestMethod ,
249
+ val mockServerConfigs = AnnotationSupport .findRepeatableAnnotations (extensionContext.requiredTestClass ,
244
250
MockServerConfig ::class .java)
251
+ val testMethod = extensionContext.testMethod
252
+ val mockServerConfigMethod = if (testMethod.isPresent) {
253
+ AnnotationSupport .findAnnotation(testMethod.get(), MockServerConfig ::class .java)
254
+ } else Optional .empty()
255
+ val mockServerConfigMethods = if (testMethod.isPresent) {
256
+ AnnotationSupport .findRepeatableAnnotations(testMethod.get(), MockServerConfig ::class .java)
257
+ } else emptyList()
258
+
245
259
return mockServerConfig != null && mockServerConfig.isPresent ||
246
- mockServerConfigMethod != null && mockServerConfigMethod.isPresent
260
+ mockServerConfigs.isNotEmpty() ||
261
+ mockServerConfigMethod != null && mockServerConfigMethod.isPresent ||
262
+ mockServerConfigMethods.isNotEmpty()
247
263
}
248
264
249
- private fun mockServerConfigFromAnnotation (context : ExtensionContext ): MockProviderConfig ? {
250
- val mockServerConfigMethod = if (context.testMethod.isPresent)
265
+ private fun mockServerConfigFromAnnotation (
266
+ context : ExtensionContext ,
267
+ providerInfo : ProviderInfo ?
268
+ ): MockProviderConfig ? {
269
+ val mockServerConfigFromMethod = if (context.testMethod.isPresent)
251
270
AnnotationSupport .findAnnotation(context.testMethod.get(), MockServerConfig ::class .java)
252
271
else null
253
- return if (mockServerConfigMethod != null && mockServerConfigMethod.isPresent) {
254
- MockProviderConfig .fromMockServerAnnotation(mockServerConfigMethod)
255
- } else {
256
- val mockServerConfig = AnnotationSupport .findAnnotation(context.requiredTestClass,
257
- MockServerConfig ::class .java)
258
- if (mockServerConfig != null && mockServerConfig.isPresent) {
272
+ val mockServerConfigsFromMethod = if (context.testMethod.isPresent)
273
+ AnnotationSupport .findRepeatableAnnotations(context.testMethod.get(), MockServerConfig ::class .java)
274
+ else emptyList()
275
+ val mockServerConfig = AnnotationSupport .findAnnotation(context.requiredTestClass, MockServerConfig ::class .java)
276
+ val mockServerConfigs = AnnotationSupport .findRepeatableAnnotations(context.requiredTestClass,
277
+ MockServerConfig ::class .java)
278
+
279
+ return when {
280
+ mockServerConfigFromMethod != null && mockServerConfigFromMethod.isPresent ->
281
+ MockProviderConfig .fromMockServerAnnotation(mockServerConfigFromMethod)
282
+
283
+ mockServerConfig != null && mockServerConfig.isPresent ->
259
284
MockProviderConfig .fromMockServerAnnotation(mockServerConfig)
260
- } else {
261
- null
285
+
286
+ mockServerConfigsFromMethod.isNotEmpty() -> {
287
+ val config = if (providerInfo != null ) {
288
+ Optional .ofNullable(mockServerConfigsFromMethod.firstOrNull { it.providerName == providerInfo.providerName })
289
+ } else {
290
+ Optional .ofNullable(mockServerConfigsFromMethod.firstOrNull())
291
+ }
292
+ MockProviderConfig .fromMockServerAnnotation(config)
293
+ }
294
+
295
+ mockServerConfigs.isNotEmpty() -> {
296
+ val config = if (providerInfo != null ) {
297
+ Optional .ofNullable(mockServerConfigs.firstOrNull { it.providerName == providerInfo.providerName })
298
+ } else {
299
+ Optional .ofNullable(mockServerConfigs.firstOrNull())
300
+ }
301
+ MockProviderConfig .fromMockServerAnnotation(config)
262
302
}
303
+
304
+ else -> null
263
305
}
264
306
}
265
307
@@ -269,7 +311,8 @@ class PactConsumerTestExt : Extension, BeforeTestExecutionCallback, BeforeAllCal
269
311
val providerInfo = when {
270
312
store[" providers" ] != null -> store[" providers" ] as List <Pair <ProviderInfo , String >>
271
313
else -> {
272
- val methodAnnotation = if (context.testMethod.isPresent && AnnotationSupport .isAnnotated(context.testMethod.get(), PactTestFor ::class .java)) {
314
+ val methodAnnotation = if (context.testMethod.isPresent &&
315
+ AnnotationSupport .isAnnotated(context.testMethod.get(), PactTestFor ::class .java)) {
273
316
val testMethod = context.testMethod.get()
274
317
logger.debug { " Found @PactTestFor annotation on test method $testMethod " }
275
318
AnnotationSupport .findAnnotation(testMethod, PactTestFor ::class .java).get()
@@ -281,7 +324,9 @@ class PactConsumerTestExt : Extension, BeforeTestExecutionCallback, BeforeAllCal
281
324
logger.debug { " Found @PactTestFor annotation on test ${context.requiredTestClass} " }
282
325
AnnotationSupport .findAnnotation(context.requiredTestClass, PactTestFor ::class .java).get()
283
326
} else if (AnnotationSupport .isAnnotated(context.requiredTestClass, Nested ::class .java)) {
284
- logger.debug { " Found @Nested annotation on test class ${context.requiredTestClass} , will search the enclosing classes" }
327
+ logger.debug {
328
+ " Found @Nested annotation on test class ${context.requiredTestClass} , will search the enclosing classes"
329
+ }
285
330
val searchResult = Annotations .searchForAnnotation(context.requiredTestClass.kotlin, PactTestFor ::class )
286
331
if (searchResult != null ) {
287
332
logger.debug { " Found @PactTestFor annotation on outer $searchResult " }
@@ -293,53 +338,49 @@ class PactConsumerTestExt : Extension, BeforeTestExecutionCallback, BeforeAllCal
293
338
null
294
339
}
295
340
296
- val mockServerConfig = mockServerConfigFromAnnotation(context)
341
+ val providerInfo = when {
342
+ classAnnotation != null && methodAnnotation != null ->
343
+ ProviderInfo .fromAnnotation(methodAnnotation)
344
+ .merge(ProviderInfo .fromAnnotation(classAnnotation))
345
+ classAnnotation != null -> ProviderInfo .fromAnnotation(classAnnotation)
346
+ methodAnnotation != null -> ProviderInfo .fromAnnotation(methodAnnotation)
347
+ else -> {
348
+ logger.warn { " No @PactTestFor annotation found on test class, using defaults" }
349
+ null
350
+ }
351
+ }
297
352
298
353
val providers = when {
299
- classAnnotation != null && methodAnnotation != null -> {
300
- val provider = ProviderInfo .fromAnnotation(methodAnnotation)
301
- .merge(ProviderInfo .fromAnnotation(classAnnotation))
302
- .withMockServerConfig(mockServerConfig)
354
+ providerInfo != null -> {
303
355
when {
304
- methodAnnotation.pactMethods.isNotEmpty() -> {
356
+ methodAnnotation != null -> if (methodAnnotation .pactMethods.isNotEmpty()) {
305
357
methodAnnotation.pactMethods.map {
306
358
val providerName = providerNameFromPactMethod(it, context)
307
- provider.copy(providerName = providerName) to it
359
+ val provider = providerInfo.copy(providerName = providerName)
360
+ val mockServerConfig = mockServerConfigFromAnnotation(context, provider)
361
+ provider.withMockServerConfig(mockServerConfig) to it
308
362
}
363
+ } else {
364
+ val mockServerConfig = mockServerConfigFromAnnotation(context, providerInfo)
365
+ val provider = providerInfo.withMockServerConfig(mockServerConfig)
366
+ listOf (provider to methodAnnotation.pactMethod)
309
367
}
310
- classAnnotation.pactMethods.isNotEmpty() -> {
368
+ classAnnotation != null -> if (classAnnotation .pactMethods.isNotEmpty()) {
311
369
classAnnotation.pactMethods.map {
312
370
val providerName = providerNameFromPactMethod(it, context)
313
- provider.copy(providerName = providerName) to it
371
+ val provider = providerInfo.copy(providerName = providerName)
372
+ val mockServerConfig = mockServerConfigFromAnnotation(context, provider)
373
+ provider.withMockServerConfig(mockServerConfig) to it
314
374
}
375
+ } else {
376
+ val mockServerConfig = mockServerConfigFromAnnotation(context, providerInfo)
377
+ val provider = providerInfo.withMockServerConfig(mockServerConfig)
378
+ listOf (provider to classAnnotation.pactMethod)
315
379
}
316
- else -> listOf (provider to methodAnnotation.pactMethod.ifEmpty { classAnnotation.pactMethod })
317
- }
318
- }
319
-
320
- classAnnotation != null -> {
321
- val annotation = ProviderInfo .fromAnnotation(classAnnotation)
322
- .withMockServerConfig(mockServerConfig)
323
- if (classAnnotation.pactMethods.isNotEmpty()) {
324
- classAnnotation.pactMethods.map {
325
- val providerName = providerNameFromPactMethod(it, context)
326
- annotation.copy(providerName = providerName) to it
327
- }
328
- } else {
329
- listOf (annotation to classAnnotation.pactMethod)
330
- }
331
- }
332
-
333
- methodAnnotation != null -> {
334
- val annotation = ProviderInfo .fromAnnotation(methodAnnotation)
335
- .withMockServerConfig(mockServerConfig)
336
- if (methodAnnotation.pactMethods.isNotEmpty()) {
337
- methodAnnotation.pactMethods.map {
338
- val providerName = providerNameFromPactMethod(it, context)
339
- annotation.copy(providerName = providerName) to it
380
+ else -> {
381
+ logger.warn { " No @PactTestFor annotation found on test class, using defaults" }
382
+ listOf (ProviderInfo () to " " )
340
383
}
341
- } else {
342
- listOf (annotation to methodAnnotation.pactMethod)
343
384
}
344
385
}
345
386
else -> {
0 commit comments