Julián Álvarez
01/20/2023, 10:38 AMIvan Mikhalka
01/21/2023, 2:30 PMpath/to/endpoint/userId/12345
and then replace it on the fly.
When storing pact file locally, we used to use sed
for replacing placeholder with actual id, like sed s/12345/$ACTUAL_USERID/g
, but it’s not the case when switching to pact broker.
Could this be done via requestFilter
from plugin or somehow else?
I know it’s not the best practice, but we need some workaround for nowOnur
01/23/2023, 1:06 PM<dependency>
<groupId>au.com.dius.pact.provider</groupId>
<artifactId>junit5</artifactId>
<version>4.4.4</version>
<exclusions>
<exclusion>
<groupId>io.ktor</groupId>
<artifactId>ktor-network-tls-certificates</artifactId>
</exclusion>
<exclusion>
<groupId>io.ktor</groupId>
<artifactId>ktor-server-netty</artifactId>
</exclusion>
<exclusion>
<groupId>au.com.dius.pact.core</groupId>
<artifactId>model</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>au.com.dius.pact.consumer</groupId>
<artifactId>junit5</artifactId>
<version>4.4.4</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>io.ktor</groupId>
<artifactId>ktor-network-tls-certificates</artifactId>
</exclusion>
<exclusion>
<groupId>io.ktor</groupId>
<artifactId>ktor-server-netty</artifactId>
</exclusion>
<exclusion>
<groupId>au.com.dius.pact.core</groupId>
<artifactId>model</artifactId>
</exclusion>
</exclusions>
</dependency>
If I do not exclude any of these libraries, I am facing the below problem when I debug the tests in IntelliJ. This happens only for debugging, not running the tests.
Connected to the target VM, address: ‘127.0.0.1:52632’, transport: ‘socket’
Internal Error occurred.
org.junit.platform.commons.JUnitException: TestEngine with ID ‘junit-jupiter’ failed to discover tests
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverEngineRoot(EngineDiscoveryOrchestrator.java:160)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverSafely(EngineDiscoveryOrchestrator.java:132)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discover(EngineDiscoveryOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discover(EngineDiscoveryOrchestrator.java:78)
at org.junit.platform.launcher.core.DefaultLauncher.discover(DefaultLauncher.java:110)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: org.junit.platform.commons.JUnitException: MethodSelector [className = ‘com.emirates.ocsl.skeleton.ct.tests.SkeletonCT’, methodName = ‘iGetResponseSuccessfully’, methodParameterTypes = ‘’] resolution failed
at org.junit.platform.launcher.listeners.discovery.AbortOnFailureLauncherDiscoveryListener.selectorProcessed(AbortOnFailureLauncherDiscoveryListener.java:39)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolveCompletely(EngineDiscoveryRequestResolution.java:103)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.run(EngineDiscoveryRequestResolution.java:83)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver.resolve(EngineDiscoveryRequestResolver.java:113)
at org.junit.jupiter.engine.discovery.DiscoverySelectorResolver.resolveSelectors(DiscoverySelectorResolver.java:46)
at org.junit.jupiter.engine.JupiterTestEngine.discover(JupiterTestEngine.java:69)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverEngineRoot(EngineDiscoveryOrchestrator.java:152)
... 13 more
Caused by: java.lang.ClassCircularityError: java/lang/WeakPairMap$Pair$Weak
at java.base/java.lang.WeakPairMap$Pair.weak(WeakPairMap.java:201)
at java.base/java.lang.WeakPairMap.putIfAbsent(WeakPairMap.java:123)
at java.base/java.lang.Module.implAddReads(Module.java:488)
at java.base/java.lang.Module.implAddReads(Module.java:449)
at java.base/java.lang.System$2.addReads(System.java:2335)
at java.base/jdk.internal.module.Modules.addReads(Modules.java:90)
at java.base/java.lang.reflect.Proxy$ProxyBuilder.lambda$getDynamicModule$1(Proxy.java:918)
at java.base/jdk.internal.loader.AbstractClassLoaderValue$Memoizer.get(AbstractClassLoaderValue.java:329)
at java.base/jdk.internal.loader.AbstractClassLoaderValue.computeIfAbsent(AbstractClassLoaderValue.java:205)
at java.base/java.lang.reflect.Proxy$ProxyBuilder.getDynamicModule(Proxy.java:908)
at java.base/java.lang.reflect.Proxy$ProxyBuilder.mapToModule(Proxy.java:846)
at java.base/java.lang.reflect.Proxy$ProxyBuilder.<init>(Proxy.java:651)
at java.base/java.lang.reflect.Proxy$ProxyBuilder.<init>(Proxy.java:656)
at java.base/java.lang.reflect.Proxy.lambda$getProxyConstructor$0(Proxy.java:429)
at java.base/jdk.internal.loader.AbstractClassLoaderValue$Memoizer.get(AbstractClassLoaderValue.java:329)
at java.base/jdk.internal.loader.AbstractClassLoaderValue.computeIfAbsent(AbstractClassLoaderValue.java:205)
at java.base/java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:427)
at java.base/java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1037)
at java.base/sun.reflect.annotation.AnnotationParser$1.run(AnnotationParser.java:302)
at java.base/sun.reflect.annotation.AnnotationParser$1.run(AnnotationParser.java:300)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
at java.base/sun.reflect.annotation.AnnotationParser.annotationForMap(AnnotationParser.java:300)
at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:289)
at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:121)
at java.base/sun.reflect.annotation.AnnotationParser.parseSelectAnnotations(AnnotationParser.java:102)
at java.base/sun.reflect.annotation.AnnotationType.<init>(AnnotationType.java:146)
at java.base/sun.reflect.annotation.AnnotationType.getInstance(AnnotationType.java:85)
at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:262)
at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:121)
at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:73)
at java.base/java.lang.Class.createAnnotationData(Class.java:4068)
at java.base/java.lang.Class.annotationData(Class.java:4057)
at java.base/java.lang.Class.getAnnotation(Class.java:3940)
at java.base/java.lang.reflect.AnnotatedElement.isAnnotationPresent(AnnotatedElement.java:292)
at java.base/java.lang.Class.isAnnotationPresent(Class.java:3950)
at org.junit.platform.commons.util.AnnotationUtils.findAnnotation(AnnotationUtils.java:136)
at org.junit.platform.commons.util.AnnotationUtils.isAnnotated(AnnotationUtils.java:105)
at org.junit.jupiter.engine.discovery.predicates.IsTestableMethod.test(IsTestableMethod.java:52)
at org.junit.jupiter.engine.discovery.predicates.IsTestMethod.test(IsTestMethod.java:23)
at org.junit.jupiter.engine.discovery.predicates.IsTestableMethod.test(IsTestableMethod.java:26)
at java.base/java.util.function.Predicate.lambda$or$2(Predicate.java:101)
at java.base/java.util.function.Predicate.lambda$or$2(Predicate.java:101)
at org.junit.platform.commons.util.ReflectionUtils.findMethod(ReflectionUtils.java:1368)
at org.junit.platform.commons.util.ReflectionUtils.isMethodPresent(ReflectionUtils.java:1267)
at org.junit.jupiter.engine.discovery.predicates.IsTestClassWithTests.hasTestOrTestFactoryOrTestTemplateMethods(IsTestClassWithTests.java:50)
at org.junit.jupiter.engine.discovery.predicates.IsTestClassWithTests.test(IsTestClassWithTests.java:46)
at org.junit.jupiter.engine.discovery.predicates.IsTestClassWithTests.test(IsTestClassWithTests.java:27)
at java.base/java.util.function.Predicate.lambda$or$2(Predicate.java:101)
at org.junit.jupiter.engine.discovery.MethodSelectorResolver.resolve(MethodSelectorResolver.java:87)
at org.junit.jupiter.engine.discovery.MethodSelectorResolver.resolve(MethodSelectorResolver.java:75)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.lambda$resolve$2(EngineDiscoveryRequestResolution.java:150)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1602)
at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:189)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:126)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolveCompletely(EngineDiscoveryRequestResolution.java:92)BENJAMIN J HESS
01/24/2023, 12:00 AMThibaut Bodart
01/25/2023, 9:23 AMarrayContaining
.
I need this logic for an array that is not defined as a value of an object property. Instead, the array is returned as the body of the response.
[
{....},
{....}
]
Ideally, I would need a newJsonArrayContaining
method in LambdaDsl
. See an example below.
return logAndReturn(builder.given("multiple connections exists")
.uponReceiving("request to get all connections")
.method("GET")
.path("/connections")
.headers(headers())
.willRespondWith()
.status(200)
.headers(headers())
.body(newJsonArrayContaining(arr -> {
......
});
}).build()));
As I understand it, there is currently no way to use arrayContaining
in this situation. Is my understanding correct?Thibaut Bodart
01/25/2023, 11:06 PM4.3.17
to 4.4.4
since I would like to use the V4 Pact specifications.
My response is in JSON format and only contains a UUID. See below a valid JSON response.
"08f7a210-95db-4827-bcc8-d2025ba506cf"
I am using the following code to define the interaction:
...
.willRespondWith()
.status(201)
.headers(headers())
.body(PactDslJsonRootValue.uuid(JOB_ID)));
With 4.3.17
, using a Pact v3 contract, the generated contract looks like:
"response": {
"body": "\"08f7a210-95db-4827-bcc8-d2025ba506cf\"",
.....
}
With 4.4.4
, using a Pact v4 contract, it looks like:
"response": {
"body": {
"content": "08f7a210-95db-4827-bcc8-d2025ba506cf",
"contentType": "application/json",
"encoded": false
},
.....
}
The content value is not a valid JSON value in the case of 4.4.4
. For this reason, the contract cannot be verified by the provider (also using pact-jvm 4.4.4
). See the exception below. This is expected since "08f7a210-95db-4827-bcc8-d2025ba506cf"
is not a valid JSON document whereas "\"08f7a210-95db-4827-bcc8-d2025ba506cf\""
is.
1.1) Invalid JSON (1:5), found unexpected character '7'
Am I doing something wrong? If I modify the contract manually as illustrated below, the provider can successfully verify it. Is there a way to generate the response below using the Pact DSL?
"response": {
"body": {
"content": "\"08f7a210-95db-4827-bcc8-d2025ba506cf\"",
"contentType": "application/json",
"encoded": false
},
Thanks in advance!Ivan Mikhalka
01/27/2023, 5:10 AM4.1.39
, using Pactflow as a pact broker. There is a several consumers for same provider, and I can run verification for all consumers using similar config:
fromPactBroker {
withSelectors {
selector('tagConsumer1', true, null, 'Consumer1')
selector('tagConsumer2', true, null, 'Consumer2')
}
}
via command
`./gradlew pactVerify -Ppact.verifier.publishResults=true -Dpact.provider.branch=git branch --show-current
-Dpact.provider.tag=`git branch --show-current``
How can I run verification for only one specified consumer?Kevin de Boer
01/30/2023, 1:48 PM@Test
@PactTestFor(providerName = "provider1", port = "1234")
public void example(MockServer provider1mock) {
...
}
However, when I do this in a multiprovider test:
@Test
@PactTestFor(pactMethods = {"createProvider1Pact", "createProvider2Pact"}, port = "1234")
public void example(@ForProvider("provider1") MockServer provider1mock, @ForProvider("provider2") MockServer provider2mock) {
...
}
I get an “address already in used” exception. Which is logical since I instantiate 2 instances of mockserver, and only provide 1 port. It tries to launch both on the same port.
However I have found no way of specifying which mockserver should use which port. Is there a way to do this?
I could not find anything in the documentation or source code, though I am unfamiliar with kotlin, I may have missed something. I tried making a subclass of MockServer and set the port myself, but then I ran into injection/instantiation issues with my new class.
Alternatively, i have also not found a way to let the application use whatever random port is chosen for the mock.Onur
01/31/2023, 6:13 AMChimein
01/31/2023, 11:51 AMSebastian Suarez
01/31/2023, 6:25 PMUlises Cervino
02/01/2023, 10:33 AMID
it checks that the ID of the returned entity matchesUlises Cervino
02/01/2023, 10:34 AMUlises Cervino
02/01/2023, 10:34 AMUlises Cervino
02/01/2023, 10:34 AMGitHub
02/02/2023, 10:26 PMPavithra Navaneeth
02/03/2023, 3:17 AMUlises Cervino
02/03/2023, 2:16 PMvalueFromProviderState
in responses? I'm struggling to figure out how this work. The test I have in mind is a consumer saying "when I GET /entity/1 I expect a response like {id: 1}" for instance, where 1
in the path matches the 1
in the response (I already have pathFromProviderState
working fine)Ulises Cervino
02/03/2023, 2:17 PMbody.valueFromProviderState(
"basketId",
"basketId",
existingBasketId.toString())
Ulises Cervino
02/03/2023, 2:17 PM"matchingRules": {
"body": {
"$.basketId": {
"combine": "AND",
"matchers": [
{
"match": "type"
}
]
},
Ulises Cervino
02/03/2023, 2:17 PM1.1) body: $.basketId Expected "698c7e00-1e27-436e-a2e6-f7dd94ea98a7" to be null
Ulises Cervino
02/03/2023, 2:18 PMMap liveBasketExists(Map _ignored_params) {
Map<String, Object> state = new HashMap<>();
InternalBasket internalBasket =
repository.createBasket(TestSupport.Repository.basketWithDefaults()).orElseThrow();
// the key in this state-map corresponds to the variable in the expression in the consumer
// test, i.e. in the
// example consumer test we have a call like .pathFromProviderState("/${basketId}", ...)
state.put("basketId", internalBasket.getBasketId());
return state;
}
Sebastian Suarez
02/03/2023, 7:26 PMpackage consumer.pact.springboot;
import org.junit.jupiter.api.extension.ExtendWith;
import au.com.dius.pact.consumer.MockServer;
import au.com.dius.pact.core.model.RequestResponsePact;
import au.com.dius.pact.core.model.annotations.Pact;
import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
import au.com.dius.pact.consumer.junit5.PactConsumerTestExt;
import au.com.dius.pact.consumer.junit5.PactTestFor;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.MatcherAssert.assertThat;
import static <http://org.hamcrest.Matchers.is|org.hamcrest.Matchers.is>;
@ExtendWith(PactConsumerTestExt.class)
@PactTestFor(providerName = "provider-springboot")
class UserPactTest {
@Pact(consumer="consumer-springboot")
public RequestResponsePact getUser(PactDslWithProvider builder) {
PactDslJsonBody body = new PactDslJsonBody();
body.stringType("id", "1");
body.stringType("name", "Sebastian Suarez");
body.stringType("email", "<mailto:sebastian@email.com|sebastian@email.com>");
body.stringType("phone", "3145289654");
body.stringType("password", "xhzASfe&1");
return builder
.given("a user with ID 1 exists")
.uponReceiving("a request to get a user")
.path("/api/v1/users/1")
.method("GET")
.headers(headers())
.willRespondWith()
.status(200)
.body(body)
.toPact();
}
@Test
@PactTestFor(pactMethod = "getUser")
void testGetProduct(MockServer mockServer) throws IOException {
UserData user = new UserRequest().setUrl(mockServer.getUrl()).getUser(1);
assertThat(user.getName(), is("Sebastian Suarez"));
}
private Map<String, String> headers() {
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json; charset=utf-8");
return headers;
}
}
package consumer.pact.springboot;
import org.apache.http.client.fluent.Request;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.List;
public class UserRequest {
private String url;
public UserRequest setUrl(String url) {
this.url = url;
return this;
}
public UserData getUser(int id) throws IOException {
return Request.Get(this.url + "/api/v1/users/" + id)
.addHeader("Accept", "application/json")
.execute().handleResponse(httpResponse -> {
try {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(httpResponse.getEntity().getContent(), UserData.class);
} catch (JsonMappingException e) {
throw new IOException(e);
}
});
}
}
Pavithra Navaneeth
02/06/2023, 12:42 AMItzhak Eretz Kdosha
02/06/2023, 12:16 PMBasu Silviu
02/06/2023, 12:38 PMscheme
, host
, port
are deprecated, but the documentation doesn't explicitly say what replaced them. I do see a url
, Can any of you please confirm if url
replaces the other 3?Basu Silviu
02/06/2023, 12:38 PMÉdouard Lopez
02/06/2023, 4:10 PMjava.lang.IllegalArgumentException: Invalid pact broker host specified ('${pactbroker.host:}'). Please provide a valid host or specify the system property 'pactbroker.host'.
with the command
./gradlew testContract \
-Ppact.verifier.publishResults=true \
-Ppactbroker.url="<http://foo.bar>" \
--info
Ulises Cervino
02/06/2023, 7:16 PMUlises Cervino
02/06/2023, 7:17 PM<http://miningmadness.com|miningmadness.com>