pact-foundation / pact-jvm

JVM version of Pact. Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.
https://docs.pact.io
Apache License 2.0
1.08k stars 479 forks source link

pactVerify failed on pact records with request contains spaces in the URL #693

Open minhdoan159 opened 6 years ago

minhdoan159 commented 6 years ago

I want to create a record to test the request: /odata/CHAIR?$filter=CREATED_BY/FIRST_NAME eq 'LIMS'&$orderby=Id asc

With the code as below: .path("/odata/CHAIR") .query("$filter=CREATED_BY/FIRST_NAME eq 'LIMS'&$orderby=Id asc") The record published to pact broker has format: { "method": "GET", "path": "/odata/CHAIR", "query": "$filter=CREATED_BY%2F_FIRST_NAME+eq+%27LIMS%27&$orderby=Id+asc" } and if i run pactVerify the record, a error code 400 is received { "error": { "code": "1001", "message": "The types 'Edm.Boolean' and 'Edm.String' are not compatible." } } I think it is a known issue with "+" in the request, instead of %20 And i have tried with: .path("/odata/CHAIR") .encodedQuery("$filter=CREATED_BY%2FCI_FIRST_NAME%20eq%20%27LIMS%27&$orderby=Id%27asc") and the respective record published on broker as below: { "method": "GET", "path": "/odata/CHAIR", "query": "$filter=CREATED_BY%252FIRST_NAME%2520eq%2520%2527LIMS%2527&$orderby=Id%2520asc" } The query is double encoded so the pactVerify also failed with 400 error code Could you please help me on it? Many thanks, team!

uglyog commented 6 years ago

What version of Pact-JVM are you using?

minhdoan159 commented 6 years ago

I am using 'au.com.dius:pact-jvm-consumer-junit_2.11:3.5.9'

uglyog commented 6 years ago

Try version 3.5.13 or later, the URL encoding was fixed in that version.

minhdoan159 commented 6 years ago

I upgraded to testCompile 'au.com.dius:pact-jvm-consumer-junit_2.11:3.5.17' But the issue still happens

minhdoan159 commented 6 years ago

@uglyog Any new investigation on it, bro? The pact-jvm has been changed to latest as info on Broker: "pact-jvm": { "version": "3.5.17" } But the query part still contains '+': "query": $filter=CREATOR%2FSTATUS+eq+%27Full+Time%27+and+CHAIR_TYPE+eq+%27BENCH%27&$orderby=Id+asc" Please help me on it! Many thanks!

rholshausen commented 6 years ago

Is that query in your pact file, or the request that is being generated when the provider is being validated?

minhdoan159 commented 6 years ago

The query is displayed on the Broker UI, but the query displayed in Pact file still: "$filter": [ "CREATOE/STATUS eq 'Full Time' and CHAIR_TYPE eq 'BENCH'" ], "$orderby": [ "Id asc" ] And then i executed the pactVerify task from provider test project, a error code 400 is received: { "error": { "code": "1001", "message": "The types 'Edm.Boolean' and 'Edm.String' are not compatible." } I am not sure how to get the request generated when executing pactverify, or we add the --debug option?

minhdoan159 commented 6 years ago

@rholshausen Did you mean i should utilize the au.com.dius.pact version 3.5.18 in gradle provider project? I have tried to configure as below in the build.gradle file:

    id 'java-library'
    id 'au.com.dius.pact' version '3.5.18'
}

But the gradle pactVerify failed with the stacktrace:


FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring root project 'ODataProviderSide'.
> No signature of method: org.gradle.util.NameValidator.asValidName() is applicable for argument types: (org.codehaus.groovy.runtime.GStringImpl) values: [pactVerify_Comment_Provider]

* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Exception is:
org.gradle.api.ProjectConfigurationException: A problem occurred configuring root project 'ODataProviderSide'.
        at org.gradle.configuration.project.LifecycleProjectEvaluator.addConfigurationFailure(LifecycleProjectEvaluator.java:109)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.onAfterEvaluateFailure(LifecycleProjectEvaluator.java:105)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:87)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.doConfigure(LifecycleProjectEvaluator.java:72)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.access$100(LifecycleProjectEvaluator.java:37)
        at org.gradle.configuration.project.LifecycleProjectEvaluator$ConfigureProject.run(LifecycleProjectEvaluator.java:125)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:317)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:309)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:185)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:97)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:52)
        at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:677)
        at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:138)
        at org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:35)
        at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:60)
        at org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:41)
        at org.gradle.initialization.DefaultGradleLauncher$ConfigureBuild.run(DefaultGradleLauncher.java:262)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:317)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:309)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:185)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:97)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.initialization.DefaultGradleLauncher.configureBuild(DefaultGradleLauncher.java:175)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:132)
        at org.gradle.initialization.DefaultGradleLauncher.executeTasks(DefaultGradleLauncher.java:115)
        at org.gradle.internal.invocation.GradleBuildController$1.call(GradleBuildController.java:77)
        at org.gradle.internal.invocation.GradleBuildController$1.call(GradleBuildController.java:74)
        at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:152)
        at org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:38)
        at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:96)
        at org.gradle.internal.invocation.GradleBuildController.run(GradleBuildController.java:74)
        at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
        at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
        at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)
        at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.run(RunAsBuildOperationBuildActionRunner.java:47)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:317)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:309)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:185)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:97)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:43)
        at org.gradle.tooling.internal.provider.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:51)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:50)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:46)
        at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:65)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:46)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:32)
        at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:39)
        at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:25)
        at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:80)
        at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:53)
        at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:62)
        at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:34)
        at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:36)
        at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:25)
        at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:43)
        at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:29)
        at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:59)
        at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:31)
        at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:59)
        at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:44)
        at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:46)
        at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:30)
        at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
        at org.gradle.util.Swapper.swap(Swapper.java:38)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:62)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:82)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122)
        at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
        at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:295)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: groovy.lang.MissingMethodException: No signature of method: org.gradle.util.NameValidator.asValidName() is applicable for argument types: (org.codehaus.groovy.runtime.GStringImpl) values: [pactVerify_Comment_Provider]
        at au.com.dius.pact.provider.gradle.PactPlugin$_apply_closure1$_closure3$_closure4.doCall(PactPlugin.groovy:47)
        at au.com.dius.pact.provider.gradle.PactPlugin$_apply_closure1$_closure3$_closure4.doCall(PactPlugin.groovy)
        at au.com.dius.pact.provider.gradle.PactPlugin$_apply_closure1$_closure3.doCall(PactPlugin.groovy:43)
        at org.gradle.api.internal.ClosureBackedAction.execute(ClosureBackedAction.java:71)
        at org.gradle.util.ConfigureUtil.configureTarget(ConfigureUtil.java:155)
        at org.gradle.util.ConfigureUtil.configure(ConfigureUtil.java:106)
        at org.gradle.util.ConfigureUtil$WrappedConfigureAction.execute(ConfigureUtil.java:167)
        at org.gradle.api.internal.DefaultDomainObjectCollection.all(DefaultDomainObjectCollection.java:154)
        at org.gradle.api.internal.DefaultDomainObjectCollection.all(DefaultDomainObjectCollection.java:175)
        at au.com.dius.pact.provider.gradle.PactPlugin$_apply_closure1.doCall(PactPlugin.groovy:41)
        at org.gradle.listener.ClosureBackedMethodInvocationDispatch.dispatch(ClosureBackedMethodInvocationDispatch.java:40)
        at org.gradle.listener.ClosureBackedMethodInvocationDispatch.dispatch(ClosureBackedMethodInvocationDispatch.java:25)
        at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:42)
        at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:230)
        at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:149)
        at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:58)
        at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:324)
        at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:234)
        at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:140)
        at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:37)
        at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
        at com.sun.proxy.$Proxy29.afterEvaluate(Unknown Source)
        at org.gradle.configuration.project.LifecycleProjectEvaluator$1.execute(LifecycleProjectEvaluator.java:83)
        at org.gradle.configuration.project.LifecycleProjectEvaluator$1.execute(LifecycleProjectEvaluator.java:80)
        at org.gradle.api.internal.project.DefaultProject.stepEvaluationListener(DefaultProject.java:1393)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:80)
        ... 88 more

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0.
See https://docs.gradle.org/4.8/userguide/command_line_interface.html#sec:command_line_warnings

BUILD FAILED in 2s

D:\pact-odata-provider\pact-odata-provider>

Please help to take a look! I have tried many times but don't know why i could not upgrade to use the newest au.com.dius.pact version. Many thanks!

rholshausen commented 6 years ago

That is a problem with Gradle 4.8. You'll have to use 4.7 or earlier until a fixed version is released.

uglyog commented 6 years ago

3.5.19 has been released and supports Gradle 4.8

minhdoan159 commented 6 years ago

@uglyog Many thanks! au.com.dius.pact 3.5.19 works well with Gradle 4.8. But the original issue still exists: .path("/odata/CHAIR") .query("$filter=CREATED_BY/FIRST_NAME eq 'LIMS'&$orderby=Id asc") The record published to pact broker has format: { "method": "GET", "path": "/odata/CHAIR", "query": "$filter=CREATED_BY%2FFIRST_NAME+eq+%27LIMS%27&$orderby=Id+asc" } and if i run pactVerify the record, a error code 400 is received "error": { "code": "1002", "message": "The system query option '$filter' has the not-allowed value 'CREATED_BY/FIRST_NAME+eq+'LIMS'+or+CREATED_BY/STATUS+eq+'Full+Time''." } { "error": { "code": "1001", "message": "The types 'Edm.Boolean' and 'Edm.String' are not compatible." } } I think it is a known issue with "+" in the request, instead of %20 And i have tried with: .path("/odata/CHAIR") .encodedQuery("$filter=CREATED_BY%2FCI_FIRST_NAME%20eq%20%27LIMS%27&$orderby=Id%27asc") and the respective record published on broker as below: { "method": "GET", "path": "/odata/CHAIR", "query": "$filter=CREATED_BY%252FIRST_NAME%2520eq%2520%2527LIMS%2527&$orderby=Id%2520asc" } Though the pact-jvm version is updated to latest as well: "metadata": { "pactSpecification": { "version": "3.0.0" }, "pact-jvm": { "version": "3.5.19" } } Please help me to resolve the issue with space in url, it blocks me!

minhdoan159 commented 6 years ago

@uglyog @rholshausen Could you please help on this issue? I am being stuck on it and can't move on.

Dyptorden commented 1 year ago

@uglyog @rholshausen @minhdoan159 Very late answer as I am a late adopter :) In case it still helps, you fix the "+" conversion to " " issue by setting the pact.verifier.disableUrlPathDecoding=true You won't find anything on google about it, and don't ask about the debugging I did to find it :). Good luck!