Giter VIP home page Giter VIP logo

pact-foundation / pact-jvm Goto Github PK

View Code? Open in Web Editor NEW
1.1K 78.0 476.0 16.35 MB

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.

Home Page: https://docs.pact.io

License: Apache License 2.0

Scala 0.82% Groovy 39.78% Java 15.81% Clojure 0.18% Kotlin 41.05% Dockerfile 0.01% Gherkin 2.35%
pact consumer-driven-contracts contract-testing hacktoberfest smartbear-supported

pact-jvm's Introduction

Pact-JVM

Pact-JVM Build Maven Central

JVM implementation of the consumer driven contract library pact.

From the Ruby Pact website:

Define a pact between service consumers and providers, enabling "consumer driven contract" testing.

Pact provides an RSpec DSL for service consumers to define the HTTP requests they will make to a service provider and the HTTP responses they expect back. These expectations are used in the consumers specs to provide a mock service provider. The interactions are recorded, and played back in the service provider specs to ensure the service provider actually does provide the response the consumer expects.

This allows testing of both sides of an integration point using fast unit tests.

This gem is inspired by the concept of "Consumer driven contracts". See https://martinfowler.com/articles/consumerDrivenContracts.html for more information.

Read Getting started with Pact for more information on how to get going.

Contact

Links

Tutorial (60 minutes)

Learn everything in Pact in 60 minutes: https://github.com/pact-foundation/pact-workshop-jvm-spring.

The workshop takes you through all of the key concepts of consumer and provider testing using a Spring boot application.

Documentation

Additional documentation can be found at docs.pact.io, in the Pact Wiki, and in the Pact-JVM wiki. Stack Overflow is also a good source of help, as is the Slack workspace.

Supported JDK and specification versions:

Branch Specification JDK Kotlin Version Latest Version Notes
4.6.x master V4 + plugins 17+ 1.8.22 4.6.13
4.5.x V4 + plugins 11+/17+(1) 1.7.20 4.5.12
4.1.x V3 8-12 1.3.72 4.1.43

Notes:

  • 1: Spring6 support library requires JDK 17+. The rest of Pact-JVM 4.5.x libs require 11+.

Previous versions (not actively supported)

Branch Specification JDK Kotlin Version Scala Versions Latest Version
4.4.x V4 + plugins 11+ 1.6.21 N/A 4.4.9
4.3.x V4 11+ 1.6.21 N/A 4.3.19
4.2.x V4 (1) 11-15 (2) 1.4.32 N/A 4.2.21
4.0.x V3 8-12 1.3.71 N/A 4.0.10
3.6.x V3 8 1.3.71 2.12 3.6.15
3.5.x V3 8 1.1.4-2 2.12, 2.11 3.5.25
3.5.x-jre7 V3 7 1.1.4-2 2.11 3.5.7-jre7.0
2.4.x V2 6 N/A 2.10, 2.11 2.4.20

Notes:

  • 1: V4 specification support is only partially implemented with 4.2.x
  • 2: v4.2.x may run on JDK 16, but the build for it does not.

NOTE: The JARs produced by this project have changed with 4.1.x to better align with Java 9 JPMS. The artefacts are now:

au.com.dius.pact:consumer
au.com.dius.pact.consumer:groovy
au.com.dius.pact.consumer:junit
au.com.dius.pact.consumer:junit5
au.com.dius.pact.consumer:java8
au.com.dius.pact.consumer:specs2_2.13
au.com.dius.pact:pact-jvm-server
au.com.dius.pact:provider
au.com.dius.pact.provider:scalatest_2.13
au.com.dius.pact.provider:spring
au.com.dius.pact.provider:maven
au.com.dius.pact:provider
au.com.dius.pact.provider:junit
au.com.dius.pact.provider:junit5
au.com.dius.pact.provider:scalasupport_2.13
au.com.dius.pact.provider:lein
au.com.dius.pact.provider:gradle
au.com.dius.pact.provider:specs2_2.13
au.com.dius.pact.provider:junit5spring
au.com.dius.pact.core:support
au.com.dius.pact.core:model
au.com.dius.pact.core:matchers
au.com.dius.pact.core:pactbroker

Service Consumers

Pact-JVM has a number of ways you can write your service consumer tests.

I Use Scala

You want to look at: pact4s.

I Use Java

You want to look at: junit for JUnit 4 tests and junit5 for JUnit 5 tests. Also, if you are using Java 11 or above, there is an updated DSL for consumer tests.

NOTE: If you are using Java 8, there is no separate Java 8 support library anymore, see the above library.

I Use Groovy or Grails

You want to look at: groovy or junit

(Use Clojure I)

Clojure can call out to Java, so have a look at junit. For an example look at example_clojure_consumer_pact_test.clj.

I Use some other jvm language or test framework

You want to look at: Consumer

My Consumer interacts with a Message Queue

As part of the V3 pact specification, we have defined a new pact file for interactions with message queues. For an implementation of a Groovy consumer test with a message pact, have a look at PactMessageBuilderSpec.groovy.

Service Providers

Once you have run your consumer tests, you will have generated some Pact files. You can then verify your service providers with these files.

I am writing a provider and want to ...

verify pacts with SBT

You want to look at: pact4s or scala-pact

verify pacts with Gradle

You want to look at: pact gradle plugin

verify pacts with Maven

You want to look at: pact maven plugin

verify pacts with JUnit tests

You want to look at: junit provider support for JUnit 4 tests and junit5 for JUnit 5 tests

verify pacts with Leiningen

You want to look at: pact leiningen plugin

verify pacts with a Spring MVC project

Have a look at spring or Spring MVC Pact Test Runner (Not maintained).

I want to verify pacts but don't want to use sbt or gradle or leiningen

You want to look at: provider

verify interactions with a message queue

As part of the V3 pact specification, we have defined a new pact file for interactions with message queues. The Gradle pact plugin supports a mechanism where you can verify V3 message pacts, have a look at pact gradle plugin. The JUnit pact library also supports verification of V3 message pacts, have a look at junit.

I Use Ruby or Go or something else

The pact-jvm libraries are pure jvm technologies and do not have any native dependencies.

However, if you have a ruby provider, the json produced by this library is compatible with the ruby pact library. You'll want to look at: Ruby Pact.

For .Net, there is Pact-net.

For JS, there is Pact-JS.

For Go, there is Pact-go.

For Rust, there is Pact-Rust.

Have a look at implementations in other languages.

I Use something completely different

There's a limit to how much we can help, however check out pact-jvm-server

How do I transport my pacts from consumers to providers?

You want to look at: Pact Broker

Which is a project that aims at providing tooling to coordinate pact generation and delivery between projects.

I want to contribute

Documentation for contributors is here.

Test Analytics

We are tracking anonymous analytics to gather important usage statistics like JVM version and operating system. To disable tracking, set the 'pact_do_not_track' system property or environment variable to 'true'.

pact-jvm's People

Contributors

abubics avatar alessio-tw avatar anto-ac avatar aplsup avatar asteffey avatar bbarke avatar benjamindebeerst avatar bethesque avatar carlzogh avatar e-ivaldi avatar fitzoh avatar jeffreymyers avatar joaogfarias avatar kenbot avatar lordofthejars avatar marcpa00 avatar markozz avatar mefellows avatar paweusz avatar pkubowicz avatar radekkoubsky avatar rejeeshg avatar rholshausen avatar ryandens avatar thetrav avatar timothyjones avatar tinexw avatar uglyog avatar venksub avatar you54f avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pact-jvm's Issues

[java] String matcher in response includes both body and regex in pact json file

When responding from a MockProvider with a string that alters on each request (e.g. a guid) both it's generated value and the regex are included in the json file. This results in pact verification failing as the real Provider's response will not match the generated value included in the pact json file when only the regex should be considered.

Type safety: recent refactor swapping two String parameters

Recently there was a refactor of the ConsumerInteractionJavaDsl swapping the method and path parameters, both typed as String. This silently broke existing tests in REA code, which still compiled. The mismatch-reporting mechanism is not yet sophisticated enough to report the nature of the mismatch to the user, so this cost us a lot of time to discover.

Can I gently suggest that refactors of this nature can no longer be considered, now that the framework has real users. We can handle backwards incompatibility, as long as breaks in functionality are clearly marked by compilation failures, and there is a clean migration path forward.

Secondly, can I suggest that typesafe parameters be aggressively preferred over String values. You can either do this by (preferably) having correct-by-construction Method and Path types, or (less preferably) a Java-style fluent API in the style of builder.withMethod("foo").withPath("bar"). Either of these would have prevented this breakage, and allowed wider latitude for framework refactoring.

documentation

Need to word people up about how the builder and the context works in the example

Result modelling

The current model of results (VerificationResult, MatchResult) follows this form:

  • trait ResultADT
    • object Success
    • class ManyFail(ResultADT*)
    • class Fail1
    • class Fail2
    • class Fail3

This is problematic for the following reasons:

  • The structure is not correct by construction; a ManyFail can be nested inside a ManyFail, forming a meaningless tree structure that must be traversed somehow
  • There are many cases, which makes pattern matching on Results more painful than it should be
  • Many of the cases appear to be incoherent with respect with each other; they are orthogonal or related concerns, and not a true OR with respect to the other cases. For instance, PactWritten or ConsumerTestsFailed
  • Because of this, the composition "and" combinator is partial, and has undefined/meaningless results for several combinations.

Perhaps a better structure would be:

  • trait ResultADT
    • object Success
    • class Fail(FailModeADT*)
  • trait FailModeADT
    • Fail1
    • Fail2
    • Fail3

The Success/Failure structure is of course isomorphic to a scalaz.VaildationNEL[FailMode, Unit], which should probably be preferred.

make it IDE friendly

People like to just type stuff and press "auto complete"

would be nice if we supported that

Consumer Tests should have a return type

PactFragment defines test as => Unit

specs2 defines test functions as returning instances of Result

We should be able to do:

def duringConsumerSpec[T](config: MockProviderConfig)(test: => [T]): VerificationResult[T] = {

Which would allow slightly better test framework integration at the cost of some extra code in our library.

Github version of sbt-git causes sbt to fail

Running sbt fails with the version of sbt-git pulled from github.

Work around to get the project to build is to comment out the sbt-git lines from project/Build.scala as well as remove pact-jvm-consumer-sbt from the list of aggregated projects.

Here is the error that occurs:

ronald@~/Development/Dius/pact-jvm[master]:sbt clean test publishLocal
[info] Loading project definition from /Users/ronald/Development/Dius/pact-jvm/project
[info] Loading project definition from /Users/ronald/.sbt/0.13/staging/6e3699da31ed35543fed/sbt-git/project
/Users/ronald/.sbt/0.13/staging/6e3699da31ed35543fed/sbt-git/build.sbt:15: error: `value` can only be used within a task or setting macro, such as :=, +=, ++=, Def.task, or Def.setting.
  val (name, repo) = if (isSnapshot.value) scalasbt("snapshots") else scalasbt("releases")
                                    ^
[error] Type error in expression
Project loading failed: (r)etry, (q)uit, (l)ast, or (i)gnore? q

Pact-JVM Consumer does not support multiple Accept types

If a pact request contains the 'Accept' header with multiple values in it, such as 'Accept: application/json, application/*+json', then the MockProvider will evaluate the body of the request as a simple string rather than trying to perform a JSON comparison of them.

Also, the Accept header is for what the server should be returning to the client, the 'Content-Type' header should be used when trying to understand the body of the request.

Groovy consumer dsl doesn't allow access to MockProviderConfig url

In a pure Java based Pact consumer test, it's possible to retrieve the MockProviderConfig url and provide it to the consumer that is accessing the mock provider.

Eg

        MockProviderConfig config = MockProviderConfig.createDefault()

        //This is the configuration object used to create the 
        configMap.services.awesomeService.url = config.url() 

Although the port parameter is optional, there is no way to get the port, therefore it needs to be specified upfront.

Ideally you could do:

       VerificationResult result = transaction_service.run() { config ->
            configMap.services.awesomeService.url = config.url()
           //......
      }

JUnit test class does not give the failed pact verifications on failure

The base JUnit test class does not give any feedback when a pact expectation is not met. Anybody following the example test class will have this issue.

On a pact failure, the example test reports the following Failure(java.lang.AssertionError: expected:<500> but was:<200>) which is not helpful.

The reason for this, is the mock server returns a 500 response when a request is not matched. The test then fails (by raising an exception). This result is then passed into the PactVerification which does not actually compare the actual requests to the expected ones because it has assumed the test has failed.

You can easily see this result by changing something in the example JUnit test case (I added an extra character to the header value) and running the test.

Twitter futures

I feel a bit weird about the whole Twitter futures thing. Scala Futures have been around for over 2 years now, it would be nice to use the standard mechanism.

Pretty printer

The framework really lacks good failure output at the moment. Highly structured information like this is much clearer with suitable indenting, but it can't be nested without some sort of dedicated pretty-printing code to thread through the "indentation-level" state.

I'm sure there's libraries out there, but at the very least the user-display formatting should be taken out of the toString methods and put in some pretty-printing rendering thing.

sbt plugin is published to the incorrect path.

The readme says to add the following line to plugins.sbt to use the plugin:
addSbtPlugin("com.dius" %% "pact-jvm-provider-sbt" % "2.0.2")
Which will fail to install looking for a path like:
http://central.maven.org/maven2/com/dius/pact-jvm-provider-sbt_2.10_0.13/2.0.2/pact-jvm-provider-sbt-2.0.2.pom

When I browsed central.maven.org it appears that the base path is actually au.com.dius and that the plugin has not been published with an sbt version since 2.0-RC5.

This for example will work:
addSbtPlugin("au.com.dius" %% "pact-jvm-provider-sbt" % "2.0-RC5")
But even changing the root path to au.com.dius will fail after 2.0-RC5 because it will look for a path like:
http://central.maven.org/maven2/au/com/dius/pact-jvm-provider-sbt_2.10_0.13/2.0.2/pact-jvm-provider-sbt-2.0.2.pom
when the plugin is actually published to:
http://central.maven.org/maven2/au/com/dius/pact-jvm-provider-sbt_2.10/2.0.2/pact-jvm-provider-sbt_2.10-2.0.2.pom
which is missing the _0.13 that sbt adds since sbt plugins are based on the sbt version.

Or at least that is the way it looks to me, someone who has only been using SBT for a few days. If there is any other input I can add to improve this ticket or help troubleshoot it please let me know.

Banish consumer server side effects

Further to the detailed analysis in #19 , the actual side-effecting Unfiltered/Finawhatever server stuff should just be some pixie-dust we sprinkle on at the end of the universe; the rest of the mechanism should run in its entirety with a pure thing that can produce a Stream[Interaction]. Currently there is too much coupling with chatty server code.

This is important, because we have observed non-determinism in various pact-jvm framework tests running on CI servers at REA. Regardless of whether that has arisen from REA-specific cosmic rays, the framework's behaviour would be much, much easier to reason about and debug with the additional purity.

deterministic pact serialization

even though key order is not important, they should be sorted deterministically on serialisation to work better with version control

Flaky provider tests

In our Bamboo CI environment, various pact-jvm tests fail nondetermistically, while they always pass locally.

The error is typically something along the lines of blah.blah.finagle.ChannelClosedException

Affected:
...provider.PactSpec, ...provider.MainSpec, ...consumer.ConsumerPactSpec, ...sbt.GitOpsSpec

Pact SBT returns exit code 0 when tests fail.

I am using travis-ci for continuous integration and noticed that if I have a failure with "sbt test" then sbt exits with a non-zero code, causing my continuous integration service to notify me of a failed test, but if "sbt verifyPacts" has an error it exits with 0 and the continuous integrations tests pass when I would have liked them to fail.

Json-independent body code

Currently a lot of the code is fervently married to having a JSON-shaped body, and using such-and-such a JSON munging library.

It looks to me that it would cost almost nothing to make the core code format-independent, and be smaller and more general at a stroke. The special matching logic could be provided with a typeclass or something.

Allow response supporting crossing site requests

In server side, when I try to use /create or /complete to create new API or verify and generate my pact file, if the server gets something wrong, say, neither 200 nor 201, header ("Access-Controller-Aloow-Origin" -> "*") will not be set, so it's not so friendly for debugging if the test has cross-domain tests.

Mock server does not handle requests with chunked encoding

Post requests with chunked transport encoding are being treated by the mock server as having no bodies.

For an example:

06:53:47.786 [Test worker] DEBUG org.apache.http.wire -  >> "POST /policyUpdateControl HTTP/1.1[\r][\n]"
06:53:47.786 [Test worker] DEBUG org.apache.http.wire -  >> "Content-Type: application/json[\r][\n]"
06:53:47.786 [Test worker] DEBUG org.apache.http.wire -  >> "Accept-Encoding: gzip[\r][\n]"
06:53:47.787 [Test worker] DEBUG org.apache.http.wire -  >> "Content-Encoding: gzip[\r][\n]"
06:53:47.787 [Test worker] DEBUG org.apache.http.wire -  >> "Transfer-Encoding: chunked[\r][\n]"
06:53:47.787 [Test worker] DEBUG org.apache.http.wire -  >> "Host: localhost:29879[\r][\n]"
06:53:47.787 [Test worker] DEBUG org.apache.http.wire -  >> "Connection: Keep-Alive[\r][\n]"
06:53:47.787 [Test worker] DEBUG org.apache.http.wire -  >> "User-Agent: au.com.ioof.ri.aia.consumer.service.pacts.AIABootstrap (ri-aia-consumer-service-jersey-client)[\r][\n]"
06:53:47.787 [Test worker] DEBUG org.apache.http.wire -  >> "[\r][\n]"
06:53:47.787 [Test worker] DEBUG org.apache.http.headers - >> POST /policyUpdateControl HTTP/1.1
06:53:47.787 [Test worker] DEBUG org.apache.http.headers - >> Content-Type: application/json
06:53:47.787 [Test worker] DEBUG org.apache.http.headers - >> Accept-Encoding: gzip
06:53:47.787 [Test worker] DEBUG org.apache.http.headers - >> Content-Encoding: gzip
06:53:47.787 [Test worker] DEBUG org.apache.http.headers - >> Transfer-Encoding: chunked
06:53:47.787 [Test worker] DEBUG org.apache.http.headers - >> Host: localhost:29879
06:53:47.787 [Test worker] DEBUG org.apache.http.headers - >> Connection: Keep-Alive
06:53:47.787 [Test worker] DEBUG org.apache.http.headers - >> User-Agent: au.com.ioof.ri.aia.consumer.service.pacts.AIABootstrap (ri-aia-consumer-service-jersey-client)
06:53:47.791 [Test worker] DEBUG org.apache.http.wire -  >> "a[\r][\n]"
06:53:47.792 [Test worker] DEBUG org.apache.http.wire -  >> "[0x1f][0x8b][0x8][0x0][0x0][0x0][0x0][0x0][0x0][0x0]"
06:53:47.792 [Test worker] DEBUG org.apache.http.wire -  >> "[\r][\n]"
06:53:47.792 [Test worker] DEBUG org.apache.http.wire -  >> "26[\r][\n]"
06:53:47.792 [Test worker] DEBUG org.apache.http.wire -  >> "[0xab]V*.I,)-V[0xb2]R[\n]"
06:53:47.792 [Test worker] DEBUG org.apache.http.wire -  >> "v[0xf5][0xb][0x89][0xf][0xf1][0x8f][0xf7][0xf4][0xb][0xe][\r]r[\r]R[0xaa][0x5][0x0]|[0x82]?9[0x1c][0x0][0x0][0x0]"
06:53:47.792 [Test worker] DEBUG org.apache.http.wire -  >> "[\r][\n]"
06:53:47.792 [Test worker] DEBUG org.apache.http.wire -  >> "0[\r][\n]"
06:53:47.792 [Test worker] DEBUG org.apache.http.wire -  >> "[\r][\n]

The mock server treats this as having no body:

06:53:47.806 [New I/O worker #10] DEBUG a.c.d.p.c.UnfilteredMockProvider - Received request:    method: POST
path: /policyUpdateControl
query: None
headers: Some(Map(Transfer-Encoding -> chunked, Content-Encoding -> gzip, Connection -> Keep-Alive, Content-Type -> application/json, Accept-Encoding -> gzip, User-Agent -> au.com.ioof.ri.aia.consumer.service.pacts.AIABootstrap (ri-aia-consumer-service-jersey-client), Host -> localhost:29879))
requestMatchers: None
body:
None
06:53:47.812 [New I/O worker #10] DEBUG a.c.dius.pact.model.RequestMatching$ - Request mismatch: List(BodyMismatch(Some({
    "status": "SENT_TO_INSURER"
}),None))
06:53:47.826 [New I/O worker #10] DEBUG a.c.d.p.c.UnfilteredMockProvider - Generating response:     status: 500
headers: Some(Map(Access-Control-Allow-Origin -> *, Content-Type -> application/json, X-Pact-Unexpected-Request -> 1))
matchers: None
body:
Some({
    "error" : "Unexpected request : \tmethod: POST\n\tpath: /policyUpdateControl\n\tquery: None\n\theaders: Some(Map(Transfer-Encoding -> chunked, Content-Encoding -> gzip, Connection -> Keep-Alive, Content-Type -> application/json, Accept-Encoding -> gzip, User-Agent -> au.com.ioof.ri.aia.consumer.service.pacts.AIABootstrap (ri-aia-consumer-service-jersey-client), Host -> localhost:29879))\n\trequestMatchers: None\n\tbody:\nNone"
})

Race condition in ConsumerPact

In ConsumerPact, the server is started, code is run, the server stopped, and the mutable Interaction list is inspected.

Since the interaction list is inspected immediately, although we know the user code has run, we can't know that the server has updated the Interaction list yet. Therefore there is a chance that some interactions will be intermittently dropped.

We could put in a small wait (50 ms or so), which would mitigate the issue, but is not technically sound. Otherwise we could maybe.... loop, stopping when the interactions are all recorded or a timeout happens? That's the best I can think of right now. :(

"query" field generated in json file not being read

We were able to generate following chuck in our pact json file from the consumer side

"interactions" : [ {
    "description" : "a request for...",
    "request" : {
      "method" : "GET",
      "path" : "/api/...",
      "query" : "...=...&...=...&..."
    },
    ...

However, when we execute this from the provider side, the query does not seem to be executed, is this expected?

Pretty printing does not order keys

Because we're saying that order of keys within a JSON object does not matter, we should order the keys when doing a text diff on the JSON string.
Otherwise we could be showing users some nasty false mismatches

Doesn't support Java 6

I was hoping to use Pact at Aconex, but they run Java 6, and the jars on Maven Central seem to have been compiled with Java 7.

Build against 2.11

One of our teams is using 2.11 and it would be super peachy if we had a pact-jvm build against it :)

Abolish reverse header matches

The reverse-header concept doesn't make sense.

The normal mode says "Here are the minimum set of headers; if any are missing, then it doesn't match".

The reverse mode says "Here are the maximum set of headers; you can have less, but if you have any extra ones, then it doesn't match".

An HTTP request will never fail when there are additional headers; servers, CDNs, browsers, etc will add all kinds of headers to requests; user code should never claim to be aware of the full set of headers that apply.

Query String not being removed from path

There seems to be a small defect in the way pact is generating the mock server when using query strings. Pact seems to not be removing the querry string from the path when matching. Below is some output.

The print out from the fragment
request:
method: GET
path: /policyUpdateControl
query: Some(status=RESPONSE_RECEIVED&insurerCode=AIA)
headers: Some(Map(Accept -> application/json))
requestMatchers: None
body:
None

The request received, printed out from pact
Received request:
method: GET
path: /policyUpdateControl?status=RESPONSE_RECEIVED&insurerCode=AIA
query: Some(insurerCode=AIA&status=RESPONSE_RECEIVED)
headers: Some(Map(Accept -> application/json, Connection -> keep-alive, Host -> localhost:38797, User-Agent -> Java/1.8.0_20))
requestMatchers: None
body:
None

[java] Support timestamps of different formats

It would be great if when declaring that a json body using PactDslJsonBody that contains a timestamp that we could specify the format of it. Then we could write something using the strftime formats along the lines of:

new PactDslJsonBody().timestamp("foo", "%Y-%m-%dT%H:%M:%S%z").toFragment();

Currently, our applications use a different timestamp format than pact-jvm and we are having to stub time during the test to match against a fixed string value. Providing this would allow us a great deal of flexibility and cleaner tests.

Feature: Special Handling for Cookies

Cookies are currently handled using normal headers, however it would be nice if we could have it split up and match on individual key value pairs within that header

Type safety: expected vs actual Requests

The only reason the reverseHeaders shenanigans worked at all is that there is another bug(s) that cancels them out.

There is pervasive confusion throughout the matching code in RequestMatching and PactVerification as to whether "expected" or "actual" values are required.

Consider: in RequestMatching, are the interactions "expected" or "actual"? They are not in any way interchangeable. The extension method in the companion object takes the interactions from a Pact, which are definitely "expected" interactions.

However, findResponse() passes if ANY of the expected interactions match the actual ones. This makes no sense of course, a pass is only meaningful if ALL the expected interactions are matched. The confusion is compounded by inconsistently putting the "actual" parameter first and "expected" second, rather than the other way around. You can see though, that it clearly passes its interactions into the "expected" slot on Matching.

In PactVerification.allExpectedInteractions, this falls apart. There is an "in" submethod, which takes an Iterable[Interaction] and an Interaction. Which is "expected" and which "actual"? We are clearly passing something marked as "actual" into the first slot, but this goes into the RequestMatching object, which should be dealing in expected objects.

In any case, types can help us out of this mess. In Scalaz, there is something called "tagged types". This lets us do this:

// marker traits
sealed trait Expected
sealed trait Actual 

def matchSomething(expected: Request @@ Expected, actual: Request @@ Actual)

This helps in these cases where we have identical types that are not in any way interchangeable. You can lift a type into the tagged version using Tag(foo). It should infer the marker type. The tag will implicitly provide a view to the underlying type, so you can just treat these two things as Requests.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.