Skip to content

Commit 68c31d0

Browse files
committed
Merge branch 'v4.4.x' into v4.5.x
2 parents f586340 + 7c07d6a commit 68c31d0

File tree

8 files changed

+162
-18
lines changed

8 files changed

+162
-18
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
To generate the log, run `git log --pretty='* %h - %s (%an, %ad)' TAGNAME..HEAD` replacing TAGNAME and HEAD as appropriate.
22

3+
# 4.4.7 - Maintenance Release
4+
5+
* 5bc8bc683 - fix: PactVerificationExtension will fail when used with other extensions in a static context #1666 (Ronald Holshausen, Fri Feb 24 12:41:00 2023 +1100)
6+
* 3010a102b - feat: Add support for JSONObject with MessagePactBuilder #1669 (Ronald Holshausen, Fri Feb 24 11:59:17 2023 +1100)
7+
* 2a9ac69db - doc: add example using MessagePactBuilder with string content #1669 (Ronald Holshausen, Fri Feb 24 11:31:08 2023 +1100)
8+
* e297ef757 - chore: update versions in readme (Ronald Holshausen, Wed Feb 15 17:52:32 2023 +1100)
9+
* 8e125575f - chore: Update JUnit5 readme (Ronald Holshausen, Wed Feb 15 17:02:12 2023 +1100)
10+
* 0ca80c4b6 - bump version to 4.4.7 (Ronald Holshausen, Wed Feb 15 17:01:23 2023 +1100)
11+
312
# 4.5.0-beta.1 - Maintenance Release
413

514
* 63559b887 - Merge branch 'master' into v4.5.x (Ronald Holshausen, Wed Feb 15 17:16:53 2023 +1100)

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,15 @@ and in the [Pact-JVM wiki](https://github.com/DiUS/pact-jvm/wiki). [Stack Overfl
4646

4747
## Supported JDK and specification versions:
4848

49-
| Branch | Specification | JDK | Kotlin Version | Latest Version | Notes |
50-
|------------------------------------------------------------------------|---------------|------|----------------|----------------|----------------------------------------|
51-
| [4.5.x](https://github.com/DiUS/pact-jvm/blob/v4.5.x/README.md) | V4 + plugins | 11+ | 1.7.20 | 4.5.0-beta.0 | |
52-
| [4.4.x](https://github.com/DiUS/pact-jvm/blob/v4.4.x/README.md) master | V4 + plugins | 11+ | 1.6.21 | 4.4.3 | |
53-
| [4.3.x](https://github.com/DiUS/pact-jvm/blob/v4.3.x/README.md) | V4 | 11+ | 1.6.21 | 4.3.19 | [Upgrade notes](./upgrade-to-4.3.x.md) |
54-
| [4.1.x](https://github.com/DiUS/pact-jvm/blob/v4.1.x/README.md) | V3 | 8-12 | 1.3.72 | 4.1.41 | |
49+
| Branch | Specification | JDK | Kotlin Version | Latest Version | Notes |
50+
|------------------------------------------------------------------------|---------------|------------|----------------|----------------|----------------------------------------|
51+
| [4.5.x](https://github.com/DiUS/pact-jvm/blob/v4.5.x/README.md) | V4 + plugins | 11+/17+(1) | 1.7.20 | 4.5.0-beta.1 | |
52+
| [4.4.x](https://github.com/DiUS/pact-jvm/blob/v4.4.x/README.md) master | V4 + plugins | 11+ | 1.6.21 | 4.4.6 | |
53+
| [4.3.x](https://github.com/DiUS/pact-jvm/blob/v4.3.x/README.md) | V4 | 11+ | 1.6.21 | 4.3.19 | [Upgrade notes](./upgrade-to-4.3.x.md) |
54+
| [4.1.x](https://github.com/DiUS/pact-jvm/blob/v4.1.x/README.md) | V3 | 8-12 | 1.3.72 | 4.1.41 | |
55+
56+
**Notes:**
57+
* **1:** Spring6 support library requires JDK 17+. The rest of Pact-JVM libs require 11+.
5558

5659
### Previous versions (not actively supported)
5760

consumer/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ The library is available on maven central using:
1414

1515
* group-id = `au.com.dius.pact`
1616
* artifact-id = `consumer`
17-
* version-id = `4.2.x`
17+
* version-id = `4.4.x`
1818

1919
## DSL Usage
2020

@@ -506,14 +506,14 @@ When you come accross the `body()` method of `PactDslWithProvider` builder start
506506
The call to `LambdaDsl` replaces the call to instance `new PactDslJsonArray()` and `new PactDslJsonBody()` of the pact library.
507507

508508
```java
509-
io.pactfoundation.consumer.dsl.LambdaDsl.*
509+
au.com.dius.pact.consumer.dsl.LambdaDsl.*
510510
```
511511

512512
### Response body as json array
513513

514514
```java
515515

516-
import static io.pactfoundation.consumer.dsl.LambdaDsl.newJsonArray;
516+
import static au.com.dius.pact.consumer.dsl.LambdaDsl.newJsonArray;
517517

518518
...
519519

@@ -534,7 +534,7 @@ builder.given("some state")
534534

535535
```java
536536

537-
import static io.pactfoundation.consumer.dsl.LambdaDsl.newJsonBody;
537+
import static au.com.dius.pact.consumer.dsl.LambdaDsl.newJsonBody;
538538

539539
...
540540

consumer/junit/src/test/groovy/au/com/dius/pact/consumer/junit/MessagePactBuilderSpec.groovy

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import au.com.dius.pact.core.model.generators.DateTimeGenerator
99
import au.com.dius.pact.core.model.messaging.Message
1010
import groovy.json.JsonSlurper
1111
import groovy.xml.XmlParser
12+
import org.json.JSONObject
1213
import spock.lang.Issue
1314
import spock.lang.Specification
1415
import spock.lang.Unroll
@@ -218,4 +219,22 @@ class MessagePactBuilderSpec extends Specification {
218219
message.contents.valueAsString() == 'a=b&c=d'
219220
message.contents.contentType.toString() == 'application/x-www-form-urlencoded'
220221
}
222+
223+
@Issue('#1669')
224+
def 'support content with JSONObject'() {
225+
given:
226+
JSONObject jsonObject = new JSONObject().put('JSON', 'Hello, World!')
227+
228+
when:
229+
def pact = new MessagePactBuilder()
230+
.consumer('MessagePactBuilderSpec')
231+
.expectsToReceive('a message with text contents')
232+
.withContent(jsonObject)
233+
.toPact()
234+
Message message = pact.interactions.first()
235+
236+
then:
237+
message.contents.valueAsString() == '{"JSON":"Hello, World!"}'
238+
message.contents.contentType.toString() == 'application/json'
239+
}
221240
}

consumer/junit5/README.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ The library is available on maven central using:
99

1010
* group-id = `au.com.dius.pact.consumer`
1111
* artifact-id = `junit5`
12-
* version-id = `4.2.X`
12+
* version-id = `4.4.X`
1313

1414
## Usage
1515

@@ -234,6 +234,26 @@ message queue or topic as a notification or event. With Pact tests, we will be t
234234
works with the messages setup as the expectations in test. This should be the message handler code that processes the
235235
actual messages that come off the message queue in production.
236236

237+
For example:
238+
239+
```java
240+
builder.given("Some Provider State")
241+
.expectsToReceive("a test message")
242+
.withContent("{\"value\": \"test\"}")
243+
.toPact();
244+
```
245+
246+
or using a Dsl object:
247+
248+
```java
249+
builder.given("Some Provider State")
250+
.expectsToReceive("a test message")
251+
.withContent(new PactDslJsonBody()
252+
.stringValue("testParam1", "value1")
253+
.stringValue("testParam2", "value2"))
254+
.toPact();
255+
```
256+
237257
You can use either the V3 Message Pact or the V4 Asynchronous Message interaction to test these types of interactions.
238258

239259
For a V3 message pact example, see [AsyncMessageTest](https://github.com/pact-foundation/pact-jvm/blob/ac6a0eae0b18183f6f453eafddb89b90741ace42/consumer/junit5/src/test/java/au/com/dius/pact/consumer/junit5/AsyncMessageTest.java).
@@ -256,7 +276,7 @@ builder.given("SomeProviderState")
256276
md.add("metadata3", 10L);
257277
md.matchRegex("partitionKey", "[A-Z]{3}\\d{2}", "ABC01");
258278
})
259-
.withContent(body)
279+
.withContent("{\"value\": \"test\"}")
260280
.toPact();
261281
```
262282

consumer/src/main/kotlin/au/com/dius/pact/consumer/MessagePactBuilder.kt

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import au.com.dius.pact.core.model.generators.Category
1818
import au.com.dius.pact.core.model.messaging.Message
1919
import au.com.dius.pact.core.model.messaging.MessagePact
2020
import au.com.dius.pact.core.model.v4.MessageContents
21+
import org.json.JSONObject
2122
import java.util.Locale
2223

2324
/**
@@ -163,7 +164,7 @@ class MessagePactBuilder @JvmOverloads constructor(
163164
*/
164165
fun withContent(body: DslPart): MessagePactBuilder {
165166
if (messages.isEmpty()) {
166-
throw InvalidPactException("expectsToReceive is required before withMetaData")
167+
throw InvalidPactException("expectsToReceive is required before withContent")
167168
}
168169

169170
val message = messages.last()
@@ -197,7 +198,7 @@ class MessagePactBuilder @JvmOverloads constructor(
197198
*/
198199
fun withContent(xmlBuilder: PactXmlBuilder): MessagePactBuilder {
199200
if (messages.isEmpty()) {
200-
throw InvalidPactException("expectsToReceive is required before withMetaData")
201+
throw InvalidPactException("expectsToReceive is required before withContent")
201202
}
202203

203204
val message = messages.last()
@@ -231,7 +232,7 @@ class MessagePactBuilder @JvmOverloads constructor(
231232
@JvmOverloads
232233
fun withContent(contents: String, contentType: String = "text/plain"): MessagePactBuilder {
233234
if (messages.isEmpty()) {
234-
throw InvalidPactException("expectsToReceive is required before withMetaData")
235+
throw InvalidPactException("expectsToReceive is required before withContent")
235236
}
236237

237238
val message = messages.last()
@@ -247,6 +248,35 @@ class MessagePactBuilder @JvmOverloads constructor(
247248
return this
248249
}
249250

251+
/**
252+
* Adds the JSON body as the message content
253+
*/
254+
fun withContent(json: JSONObject): MessagePactBuilder {
255+
if (messages.isEmpty()) {
256+
throw InvalidPactException("expectsToReceive is required before withContent")
257+
}
258+
259+
val message = messages.last()
260+
val metadata = message.contents.metadata.toMutableMap()
261+
val contentTypeEntry = metadata.entries.find {
262+
it.key.lowercase() == "contenttype" || it.key.lowercase() == "content-type"
263+
}
264+
265+
var contentType = ContentType.JSON
266+
if (contentTypeEntry == null) {
267+
metadata["contentType"] = contentType.toString()
268+
} else {
269+
contentType = ContentType(contentTypeEntry.value.toString())
270+
}
271+
272+
message.contents = message.contents.copy(
273+
contents = OptionalBody.body(json.toString().toByteArray(contentType.asCharset()), contentType),
274+
metadata = metadata
275+
)
276+
277+
return this
278+
}
279+
250280
/**
251281
* Terminates the DSL and builds a pact to represent the interactions
252282
*/

provider/junit5/src/main/kotlin/au/com/dius/pact/provider/junit5/PactVerificationExtension.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,14 @@ open class PactVerificationExtension(
7373

7474
override fun supportsParameter(parameterContext: ParameterContext, extensionContext: ExtensionContext): Boolean {
7575
val store = extensionContext.getStore(ExtensionContext.Namespace.create("pact-jvm"))
76-
val testContext = store.get("interactionContext") as PactVerificationContext
76+
val testContext = store.get("interactionContext") as PactVerificationContext?
7777
return when (parameterContext.parameter.type) {
7878
Pact::class.java -> true
7979
Interaction::class.java -> true
80-
ClassicHttpRequest::class.java, HttpRequest::class.java -> testContext.target is HttpTestTarget
80+
ClassicHttpRequest::class.java, HttpRequest::class.java -> testContext?.target is HttpTestTarget
8181
PactVerificationContext::class.java -> true
8282
ProviderVerifier::class.java -> true
83-
RequestData::class.java -> testContext.target is PluginTestTarget
83+
RequestData::class.java -> testContext?.target is PluginTestTarget
8484
else -> false
8585
}
8686
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package au.com.dius.pact.provider.junit5;
2+
3+
import au.com.dius.pact.provider.junitsupport.Provider;
4+
import au.com.dius.pact.provider.junitsupport.State;
5+
import au.com.dius.pact.provider.junitsupport.loader.PactFolder;
6+
import org.junit.jupiter.api.extension.Extension;
7+
import org.junit.jupiter.api.extension.ExtensionContext;
8+
import org.junit.jupiter.api.extension.ParameterContext;
9+
import org.junit.jupiter.api.extension.ParameterResolutionException;
10+
import org.junit.jupiter.api.extension.ParameterResolver;
11+
import org.junit.jupiter.api.extension.RegisterExtension;
12+
import org.slf4j.Logger;
13+
import org.slf4j.LoggerFactory;
14+
import org.junit.jupiter.api.TestTemplate;
15+
import org.junit.jupiter.api.extension.ExtendWith;
16+
17+
import static org.hamcrest.MatcherAssert.assertThat;
18+
import static org.hamcrest.Matchers.is;
19+
import static org.hamcrest.Matchers.notNullValue;
20+
21+
@Provider("myAwesomeService")
22+
@PactFolder("pacts")
23+
public class WithRegisteredExtensionTest {
24+
private static final Logger LOGGER = LoggerFactory.getLogger(WithRegisteredExtensionTest.class);
25+
26+
@RegisterExtension
27+
static final TestDependencyResolver resolverExt = new TestDependencyResolver(/*...*/);
28+
29+
private final TestDependency dependency;
30+
31+
public WithRegisteredExtensionTest(TestDependency dependency) {
32+
this.dependency = dependency;
33+
}
34+
35+
@TestTemplate
36+
@ExtendWith(PactVerificationInvocationContextProvider.class)
37+
void test() {
38+
assertThat(dependency, is(notNullValue()));
39+
}
40+
41+
@State("state 2")
42+
void state2() {
43+
}
44+
45+
@State("default")
46+
void stateDefault() {
47+
}
48+
49+
static class TestDependencyResolver implements Extension, ParameterResolver {
50+
@Override
51+
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
52+
return parameterContext.getParameter().getType().isAssignableFrom(TestDependency.class);
53+
}
54+
55+
@Override
56+
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
57+
return new TestDependency();
58+
}
59+
}
60+
61+
static class TestDependency {
62+
}
63+
}

0 commit comments

Comments
 (0)