Skip to content

Commit 68dd07f

Browse files
committed
feat: Support system properties or environment variables for consumer and provider annotation with JUnit4 provider tests #528 #1616
1 parent 28ff522 commit 68dd07f

File tree

6 files changed

+100
-36
lines changed

6 files changed

+100
-36
lines changed

consumer/src/test/groovy/au/com/dius/pact/consumer/dsl/PactDslRequestWithPathSpec.groovy

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,10 @@ class PactDslRequestWithPathSpec extends Specification {
159159
160160
when:
161161
def pact = consumerPactBuilder
162-
.uponReceiving("a request")
163-
.path("/api/myrequest")
164-
.method("POST")
165-
.queryMatchingDatetime("startDateTime", "yyyy-MM-dd'T'hh:mm:ss'Z'")
162+
.uponReceiving('a request')
163+
.path('/api/request')
164+
.method('POST')
165+
.queryMatchingDatetime('startDateTime', "yyyy-MM-dd'T'hh:mm:ss'Z'")
166166
.willRespondWith()
167167
.status(200)
168168
.toPact()

provider/junit/src/main/kotlin/au/com/dius/pact/provider/junit/PactRunner.kt

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package au.com.dius.pact.provider.junit
22

33
import au.com.dius.pact.core.model.Interaction
44
import au.com.dius.pact.core.model.Pact
5+
import au.com.dius.pact.core.support.expressions.DataType
6+
import au.com.dius.pact.core.support.expressions.ExpressionParser
57
import au.com.dius.pact.core.support.expressions.SystemPropertyResolver
8+
import au.com.dius.pact.core.support.expressions.ValueResolver
69
import au.com.dius.pact.core.support.json.JsonException
710
import au.com.dius.pact.provider.ProviderUtils
811
import au.com.dius.pact.provider.ProviderUtils.findAnnotation
@@ -57,7 +60,7 @@ import java.io.IOException
5760
open class PactRunner<I>(private val clazz: Class<*>) : ParentRunner<InteractionRunner<I>>(clazz) where I : Interaction {
5861

5962
private val children = mutableListOf<InteractionRunner<I>>()
60-
private var valueResolver = SystemPropertyResolver
63+
private var valueResolver: ValueResolver = SystemPropertyResolver
6164
private var initialized = false
6265

6366
private fun initialize() {
@@ -68,16 +71,8 @@ open class PactRunner<I>(private val clazz: Class<*>) : ParentRunner<Interaction
6871
if (clazz.getAnnotation(Ignore::class.java) != null) {
6972
logger.info("Ignore annotation detected, exiting")
7073
} else {
71-
val providerInfo = findAnnotation(clazz, Provider::class.java) ?: throw InitializationError(
72-
"Provider name should be specified by using ${Provider::class.java.simpleName} annotation")
73-
logger.debug { "Found annotation $providerInfo" }
74-
val serviceName = providerInfo.value
75-
76-
val consumerInfo = findAnnotation(clazz, Consumer::class.java)
77-
if (consumerInfo != null) {
78-
logger.debug { "Found annotation $consumerInfo" }
79-
}
80-
val consumerName = consumerInfo?.value
74+
val (providerInfo, serviceName) = lookupProviderInfo()
75+
val (consumerInfo, consumerName) = lookupConsumerInfo()
8176

8277
val testClass = TestClass(clazz)
8378
val ignoreNoPactsToVerify = findAnnotation(clazz, IgnoreNoPactsToVerify::class.java)
@@ -122,6 +117,31 @@ open class PactRunner<I>(private val clazz: Class<*>) : ParentRunner<Interaction
122117
initialized = true
123118
}
124119

120+
private fun lookupConsumerInfo(): Pair<Consumer?, String?> {
121+
val consumerInfo = findAnnotation(clazz, Consumer::class.java)
122+
return if (consumerInfo != null) {
123+
logger.debug { "Found annotation $consumerInfo" }
124+
val consumerName = ExpressionParser.parseExpression(consumerInfo.value, DataType.STRING, valueResolver)?.toString()
125+
Pair(consumerInfo, consumerName)
126+
} else {
127+
Pair(null, null)
128+
}
129+
}
130+
131+
private fun lookupProviderInfo(): Pair<Provider, String> {
132+
val providerInfo = findAnnotation(clazz, Provider::class.java) ?: throw InitializationError(
133+
"Provider name should be specified by using ${Provider::class.java.simpleName} annotation"
134+
)
135+
logger.debug { "Found annotation $providerInfo" }
136+
val serviceName = ExpressionParser.parseExpression(providerInfo.value, DataType.STRING, valueResolver)?.toString()
137+
if (serviceName.isNullOrEmpty()) {
138+
throw InitializationError(
139+
"Provider name specified by ${Provider::class.java.simpleName} annotation is null or empty"
140+
)
141+
}
142+
return Pair(providerInfo, serviceName)
143+
}
144+
125145
private fun checkIgnoreIoException(ignoreIoErrors: String, e: Exception) = if (ignoreIoErrors == "true") {
126146
logger.warn { "\n" + WARNING_ON_IGNORED_IOERROR.trimIndent() }
127147
logger.debug(e) { "Failed to load pact files" }

provider/junit/src/test/groovy/au/com/dius/pact/provider/junit/PactRunnerSpec.groovy

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package au.com.dius.pact.provider.junit
33
import au.com.dius.pact.core.model.Pact
44
import au.com.dius.pact.core.model.RequestResponsePact
55
import au.com.dius.pact.core.model.UrlSource
6+
import au.com.dius.pact.provider.junitsupport.Consumer
67
import au.com.dius.pact.provider.junitsupport.IgnoreNoPactsToVerify
78
import au.com.dius.pact.provider.junitsupport.Provider
89
import au.com.dius.pact.provider.junitsupport.loader.PactFolder
@@ -14,7 +15,9 @@ import au.com.dius.pact.provider.junitsupport.target.Target
1415
import au.com.dius.pact.provider.junitsupport.target.TestTarget
1516
import org.junit.runner.notification.RunNotifier
1617
import org.junit.runners.model.InitializationError
18+
import spock.lang.Issue
1719
import spock.lang.Specification
20+
import spock.util.environment.RestoreSystemProperties
1821

1922
@SuppressWarnings('UnusedObject')
2023
class PactRunnerSpec extends Specification {
@@ -116,6 +119,21 @@ class PactRunnerSpec extends Specification {
116119
Target target
117120
}
118121

122+
@Provider('${provider.name}')
123+
@PactFolder('pacts')
124+
class ProviderFromSystemPropTestClass {
125+
@TestTarget
126+
Target target
127+
}
128+
129+
@Provider('myAwesomeService')
130+
@Consumer('${consumer.name}')
131+
@PactFolder('pacts')
132+
class ConsumerFromSystemPropTestClass {
133+
@TestTarget
134+
Target target
135+
}
136+
119137
def 'PactRunner throws an exception if there is no @Provider annotation on the test class'() {
120138
when:
121139
new PactRunner(PactRunnerSpec).run(new RunNotifier())
@@ -219,4 +237,31 @@ class PactRunnerSpec extends Specification {
219237
!runner.children.empty
220238
}
221239

240+
@Issue('#528')
241+
@RestoreSystemProperties
242+
def 'PactRunner supports getting the provider name from a system property or environment variable'() {
243+
given:
244+
System.setProperty('provider.name', 'myAwesomeService')
245+
246+
when:
247+
def runner = new PactRunner(ProviderFromSystemPropTestClass)
248+
runner.run(new RunNotifier())
249+
250+
then:
251+
!runner.children.empty
252+
}
253+
254+
@Issue('#528')
255+
@RestoreSystemProperties
256+
def 'PactRunner supports getting the consumer name from a system property or environment variable'() {
257+
given:
258+
System.setProperty('consumer.name', 'anotherService')
259+
260+
when:
261+
def runner = new PactRunner(ConsumerFromSystemPropTestClass)
262+
runner.run(new RunNotifier())
263+
264+
then:
265+
!runner.children.empty
266+
}
222267
}

provider/src/main/java/au/com/dius/pact/provider/junitsupport/Provider.java

Lines changed: 0 additions & 20 deletions
This file was deleted.

provider/src/main/kotlin/au/com/dius/pact/provider/junitsupport/Consumer.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import java.lang.annotation.Inherited
44
import kotlin.annotation.Retention
55

66
/**
7-
* Used to pass consumer name to Pact runner
7+
* Used to pass consumer name to Pact runner. Can use expressions (in `${}` form) to get the value from Java system
8+
* properties or environment variables.
89
*/
910
@Retention(AnnotationRetention.RUNTIME)
1011
@Target(AnnotationTarget.CLASS, AnnotationTarget.FILE)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package au.com.dius.pact.provider.junitsupport
2+
3+
import java.lang.annotation.Inherited
4+
import kotlin.annotation.Retention
5+
6+
/**
7+
* Used to pass provider name to Pact runner. Can use expressions (in `${}` form) to get the value from Java system
8+
* properties or environment variables.
9+
*/
10+
@Retention(AnnotationRetention.RUNTIME)
11+
@Target(AnnotationTarget.CLASS, AnnotationTarget.FILE)
12+
@Inherited
13+
annotation class Provider(
14+
/**
15+
* @return provider name for pact test running
16+
*/
17+
val value: String = ""
18+
)

0 commit comments

Comments
 (0)