GithubHelp home page GithubHelp logo

pact4s's People

Contributors

agustafson avatar arknot avatar danlaudk avatar gaeljw avatar hanneshauer avatar jbwheatley avatar kflorence avatar renovate-bot avatar scala-steward 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

Watchers

 avatar  avatar  avatar

pact4s's Issues

Got "writing pacts for ... to target/pacts" from logger but no such file found

I'm using "io.github.jbwheatley" %% "pact4s-scalatest" % "0.1.0-java8"

During running test, I got this Info log
[info] Pact4s-Logger - Writing pacts for consumer Consumer(name=FraudBackofficeAPI) and provider Provider(name=FraudMlAPI) to target/pacts

However there is no such file exist in target/pacts like log mentioned. Not in my target/pacts path, and not anywhere else. Seem like it's not generated. What's wrong here?

below is my code for my test class

class PactTest extends AsyncFunSuite with Matchers with RequestResponsePactForger with Mockito with MockWSHelpers {

  val clientId = 2

  override def pact: RequestResponsePact = ConsumerPactBuilder
    .consumer("FraudBackofficeAPI")
    .hasPactWith("FraudMlAPI")
    .uponReceiving("getAllNameNationalityProbability")
    .path("http://test:port/predict-nationality")
    .method("POST")
    .headers(
      Map(
        "Content-Type" -> "application/json",
        "ClientId" ->  clientId.toString,
        "RequestId" -> "123e4567-e89b-42d3-a456-556642440000"
      )
    )
    .body(
      """{"name":"John Doe",
        |"maxResult":3}
        |""".stripMargin,
      "application/json"
    )
    .willRespondWith()
    .status(200)
    .body("""{
            |  "ARE": 0.0015790796301290394,
            |  "ARG": 0.0015750796301290393,
            |  "AUS": 0.027795471251010895
            |}
            |""".stripMargin)
    .toPact


  test("getAllNameNationalityProbability should return response for any name") {

    val config = mock[FraudBackofficeConfig]
    when(config.fraudMlServerConfig)
      .thenReturn(FraudMlServerConfig(Seq("http://test:port"), 2))

    val ws = MockWS {
      case ("POST", "http://test:port/predict-nationality") =>
        Action {
          Ok(Json.obj(
            "ARE" -> 0.0015790796301290393,
            "ARG" -> 0.0015750796301290393,
            "AUS" -> 0.027795471251010895
          ))
        }
    }

    val fraudMlClient = new FraudMlServerClientImpl(config, ws)
    val getNameNat = fraudMlClient.getAllNameNationalityProbability("John Doe")
    assert(getNameNat != null)
  }

}

ScalaTest: Tests are not run when `verifyPacts` is called asynchronously

I need to start up a server which relies on testcontainers before I can provide the correct port in the ProviderInfoBuilder -- this forces me to call verifyPacts() asynchronously (from afterContainersStart), but this results in the test suite exiting without running any tests.

As a workaround for now, I can just put a dummy test case in there, but I wonder if there is a better solution.

Automatic generation of DSL given a case class

In some simple cases, it would be nice to support automatic generation of a DSL given a case class. Similar to what the Kotlin implementation offers with basedOnRequiredConstructorFields.

Expected usage would be something like following:

case class MyModel(a: String, b: Int, c: NestedModel)
case class NestedModel(x: Seq[Long])

val dsl = DslJsonBodyBuilder.fromType[MyModel]
// Gives a LambdaDslJsonBody => Unit
// Same as what would be given to:
newJsonObject { rootObj =>
  rootObj.stringType("a")
  rootObj.integerType("b")
  rootObj.newObject("c") { o =>
    o.newArray("x") { a =>
      a.longType()
    }
  }
}

We could also provide a helper in ScalaDsl (#355 ):

newJsonObject[MyModel]

The generated DSL would be using matching types, not values.

To implement that, we will need to use TypeTag but this won't be available in Scala 3 (there are other alternatives in Scala 3). This would mean a different codebase for Scala 2 & Scala 3 which is perfectly possible but I believe the sbt structure does not allow it for now.

[Verification] How to define provider state callback?

If a consumer defines a pact using provider state callback features like .pathFromProviderState("/endpoint/${id}", "/endpoint/36"), then how to define the id value on the provider side?

Pact-JVM Junit state provider methods can return a Map of such values but I don't see an equivalent with pact4s-scalatest.

Add support for consumer version selectors for deployed and released versions

Please add support for the following keys to be used in the consumer version selectors when fetching pacts for verification:

{ "deployedOrReleased": true }

{ "deployed": true }

{ "released": true }

{ "environment": "<env name>" }

{ "deployed": true }

{ "released": true }

These keys can be used in various combinations ( eg. { "environment": "prod", released: true, consumer: "Foo" } ). Please allow any combination of keys, and do not validate them locally, as the validation rules can change over time as support is added for new selectors - just ensure that any errors returned from the API are displayed clearly to the user.

See https://github.com/pact-foundation/pact_broker/blob/master/lib/pact_broker/doc/views/provider-pacts-for-verification.markdown for the usage docs of each selector.

As more selectors will be added over time, it's my preference that the consumer version selectors are not strongly typed, and are just passed through straight from the configuration object to the API, so that we don't have to make code changes to the Pact clients each time we add new selectors. (eg. there will be new selectors coming for branch support very soon). I understand that this is not compatible with the idioms of every Pact client language however, so do whatever you need to do to make the new selectors work elegantly within your language.

Please update https://docs.pact.io/pact_broker/advanced_topics/consumer_version_selectors/ for your language once the selectors have been released.

Explore support for protobufs

what do we need to add to pact4s to support protobufs - pact-jvm already appears to have support, so should be doable

Set "enable pending" to true by default

The pending feature has been used for long enough now to show that it works, and that there is little reason to ever have it turned off any more. The Pact Broker now defaults to true if the includePendingStatus field is not set, however, this will not take effect if the client side has it set to false by default. Please set enablePending to true by default now, to ensure it is turned on for all older and future versions of the Pact Broker.

Consider printing a warning message if the user does set it to false explicitly, along the lines of "We recommend setting enablePending to true. For more information, please see https://docs.pact.io/pending"

Consider using Provided library dependencies

For example, instead of including a compile-time dependency for "org.scalatest" %% "scalatest" % "3.2.8", instead use the Provided scope: "org.scalatest" %% "scalatest" % "3.2.8 % Provided -- this way any binary compatible version of the library can be included by consumers of the library (they must specify it explicitly in their compile scope), instead of having to pull in the exact version used by this project.

[Verification] Be able to define provider state without adding a stateChangeEndpoint

Would there be a way to not having to add a custom endpoint only for the tests in order to setup the provider state when verifying pacts on the provider side?

With Pact-JVM and Junit, it's only a matter of a dedicated method that runs to setup the provider state.

I believe it would be way easier to do it in a similar way in pact4s. I'm not sure adding an endpoint only for tests is an easy task in all web frameworks and that could discourage people to use pact4s.

Add support for branches in consumer version selectors

The Pact Broker now supports branches as first class entities. You can read more about this here: https://docs.pact.io/pact_broker/branches

Description

Please add support for specifying branch related properties in the consumer version selectors that are sent to the Pact Broker when requesting pacts to verify. Please do not do any verification of the consumer version selectors on the client side - the validation rules are subject to change. Just ensure that any error response is displayed to the user.

  • For implementations that wrap the pact-ruby-standalone, update to the latest standalone version
  • For implementations that use the rust implementation, update to the latest rust version.
  • Add a String branch property to the consumer version selector (if there is a domain model for this).
  • Add a Boolean mainBranch (or main_branch for snake case languages) property consumer version selector (if there is a domain model for this).
  • Add a Boolean matchingBranch (or matching_branch for snake case languages) property consumer version selector (if there is a domain model for this).
  • Expose and document the branch, mainBranch (or main_branch for snake case languages) and matchingBranch (or matching_branch) properties in the user facing API.
  • Pass the branch, mainBranch and matchingBranch (must be camelcase) through to the relevant implementation (ruby and/or rust)

Verifying the changes

  • Publish test pacts to the test broker
export PACT_BROKER_BASE_URL="https://test.pact.dius.com.au"
export PACT_BROKER_USERNAME="dXfltyFMgNOFZAxr8io9wJ37iUpY42M"
export PACT_BROKER_PASSWORD="O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1"

docker run --rm  \
  -e PACT_BROKER_BASE_URL  \
  -e PACT_BROKER_USERNAME  \
  -e PACT_BROKER_PASSWORD  \
  pactfoundation/pact-cli:0.50.0.14 \
  publish \
  /pact/example/pacts \
  --consumer-app-version fake-git-sha-for-demo-$(date +%s) \
  --branch main

docker run --rm  \
  -e PACT_BROKER_BASE_URL  \
  -e PACT_BROKER_USERNAME  \
  -e PACT_BROKER_PASSWORD  \
  pactfoundation/pact-cli:0.50.0.14 \
  publish \
  /pact/example/pacts \
  --consumer-app-version fake-git-sha-for-demo-$(date +%s) \
  --branch feat/x
  • Using your pact client library, verify { "mainBranch": true }
    • You should receive the main pact
  • Using your pact client library, verify { "branch": "feat/x" }
    • You should receive the feat/x pact
  • Using your pact client library, verify { "matchingBranch": true } with the provider branch set to feat/x
    • You should receive the feat/x pact

Better failure information for `VerificationResult.Failed` when caused by exception

I tested this with VerificationType.AnnotatedMethod -- but I assume it's the same for request/response. The VerificationResult.Failed seems to be swallowing up the exception information by default and just shows a generic, unhelpful message like:

Verification failed due to: Request to provider method failed with an exception
ScalaTestFailureLocation: pact4s.scalatest.PactVerifier at (PactVerifier.scala:31)
org.scalatest.exceptions.TestFailedException: Verification failed due to: Request to provider method failed with an exception

I am guessing this is due to the underlying pact-jvm implementation. I do see something about an environment variable, PACT_SHOW_STACKTRACE, here: https://github.com/pact-foundation/pact-jvm/blob/master/provider/src/main/kotlin/au/com/dius/pact/provider/ProviderVerifier.kt#L358 -- perhaps that would provide extra information. Otherwise, we would have to extract it out of the errors list.

update readme.md: Is Scala3 still blocked?

The readme mentions

1 support for scala 3 is currently blocked by scala/scala3#12086, as pact-jvm is written in kotlin

is this still the case? The dotty issue is marked as fixed.

I'm asking cause a team member currently doing his bachelor-thesis introduced pact4s to our project and I just figured out now that it pulls a huge amount of dependencies into the project and if it additionally would also block us from upgrading to scala 3, that would be an even bigger problem in the future.

Thanks!

Cross-compile for Scala 2.12

We are still using Scala 2.12 for many of our projects, even though we are in the midst of upgrading to 2.13. Would be nice to cross-compile this to 2.12 so we can use it.

Add documentation about how to choose a fixed port for mock server in consumer tests

It might help in some cases to be able to set a fixed port for the mock server used when running consumer tests, this is already achievable by overriding mockProviderConfig: MockProviderConfig from RequestResponsePactForgerResources but not documented.

Example:

class MyTest ... with RequestResponsePactForger {

  override val mockProviderConfig: MockProviderConfig = MockProviderConfig.httpConfig("localhost", 9003)

  ...

}

Fix method instance used for `VerificationType.AnnotatedMethod`

The ProviderVerifier by default has:

override var providerMethodInstance: Function<Method, Any> = Function { m -> m.declaringClass.newInstance() }

I have noticed that sometimes this causes issues with references inside of the annotated method when it gets invoked, especially variables that have been defined on traits outside of the class. I have been able to work around this by assigning a variable to this inside the PactVerifier trait, and then using verifier.setProviderMethodInstance to apply it.

I will work on getting a failing test case up, and then applying the fix and making sure it passes.

[Verification] are v3 provider state generators supported yet?

Consumer pact using pathFromProviderState (see section "Having values injected from provider state callbacks
" on pact-jvm consumer docs)

.given("a user exists", Map("id" -> "6000"))....
.pathFromProviderState("/api/users/${id}", "/api/users/100")

creates a pact json file with interaction object like

{
      "description": "a request to find a user",
      "providerStates": [
        {
          "name": "a user exists",
          "params": {
            "id": "6000"
          }
        }
      ],
      "request": {
        "generators": {
          "path": {
            "dataType": "STRING",
            "expression": "/api/users/${id}",
            "type": "ProviderState"
          }
        },
        "method": "GET",
        "path": "/api/users/100"
      },
      "response": {
        "body": {
          "id": "6000"
        },
        "status": 200
      }
    }
...

Producer verification state change function

...
.withStateChangeFunction({
      case ProviderState("a user exists", params) =>
        val id = params.getOrElse("id", fail("params missing value id"))
        createUserWithId(id)
      case _ => ()
    }: PartialFunction[ProviderState, Unit])

Expected
Pact verification calls producer with path /api/users/6000

Actual
Pact verification calls producer with path /api/users/

Need help regarding the above scenario. I am not sure if it's a bug, yet to be supported feature or if I am doing something wrong.

I have been able to replicate this on the PactVerifierStateChangeFunctionSuite.scala test by using the following pact json content modified to use generators

Logs from unit test execution

[PACT4S TEST INFO] Request to mock provider server with port 49171 in test suite scalatest/requestresponse/PactVerifierStateChangeFunctionSuite.scala
[PACT4S TEST INFO] Request(method=GET, uri=/anyone-, headers=Headers(Accept-Encoding: gzip, x-gzip, deflate, Host: localhost:49171, Connection: keep-alive, User-Agent: Apache-HttpClient/5.1.1 (Java/11.0.11)))
[PACT4S TEST INFO] Response(status=404, headers=Headers(Content-Type: text/plain; charset=UTF-8, Content-Length: 9))
[PACT4S TEST INFO] Duration: 0 millis
2022-05-19 01:44:07,378 [pool-2-thread-1] DEBUG  a.c.d.pact.provider.ProviderClient - Received response: 404
2022-05-19 01:44:07,379 [pool-2-thread-1] DEBUG  a.c.d.pact.provider.ProviderClient - Response: ProviderResponse(statusCode=404, headers={Date=[Thu, 19 May 2022 00:44:07 GMT], Connection=[keep-alive], Content-Type=[text/plain; charset=UTF-8], Content-Length=[9]}, contentType=text/plain; charset=UTF-8, body=Not found)
    returns a response which
      has status code 200 (FAILED)
      has a matching body (FAILED)

Message verification support

Just wanted to start a discussion here about the best way to implement message verification support in Scala. First, a quick overview of current state:

  • there is a PactVerifier trait which works without any modification for request/response pacts

  • the trait uses ProviderVerifier().runVerificationForConsumer which supports both message and interaction (request/response) pacts

  • currently this method always defaults to request/response verification because ProviderInfo doesn't have an explicit verificationType -- it is easy to add support for this to the ProviderInfoBuilder:

    final case class ProviderInfoBuilder(
        name: String,
        protocol: String,
        host: String,
        port: Int,
        path: String,
        verificationType: PactVerification,
        pactSource: PactSource
    ) {
      private[pact4s] def toProviderInfo: ProviderInfo = {
        val p = new ProviderInfo(name, protocol, host, port, path)
        p.setVerificationType(verificationType)
        pactSource match {
          case broker: PactBroker => applyBrokerSourceToProvider(p, broker)
          case FileSource(consumer, file) =>
            p.hasPactWith(
              consumer,
              { consumer =>
                consumer.setPactSource(new PactJVMFileSource(file))
                kotlin.Unit.INSTANCE
              }
            )
            p
        }
      }
      ...
    }
  • however, this will result in verification via annotation (@PactVerifyProvider("message description")):

    @PactVerifyProvider("Resource with name 'example'")
    def exampleResource(): MessageAndMetadata = {
      val headers = Map("header-name" -> "header-value")
      val payload = """{"hello":"world"}""".getBytes
      new MessageAndMetadata(payload, headers.asJava)
    }

Full example:

class ProviderPactMessageVerificationSpec extends PactVerifier with DecorateAsJava {
  def provider: ProviderInfoBuilder = ProviderInfoBuilder(
    "provider",
    "http",
    "localhost",
    3456,
    "/",
    PactVerification.ANNOTATED_METHOD,
    FileSource("consumer", new File(getClass.getClassLoader.getResource("consumer_provider.json").getPath))
  )

  @PactVerifyProvider("Resource with name 'example'")
  def exampleResource(): MessageAndMetadata = {
    val headers = Map("header-name" -> "header-value")
    val payload = """{"hello":"world"}""".getBytes
    new MessageAndMetadata(payload, headers.asJava)
  }

  verifyPacts()
}

There are a few things awkward about this flow:

  • tying messages defined in the pact to generators using annotations feels very java-y, definitely not a normal test flow in Scala
  • the ProviderInfoBuilder should probably make defining the provider HTTP information optional -- it could be awkward for message verification where no provider states are needed (otherwise the HTTP information would be used to make requests against the provider application for states)

So what kind of test DSL do we want for linking of pact messages to message generators? And how would we integrate that with pact-jvm? Under the hood, the ProviderVerifier eventually calls verifyMessage -- we could invoke this directly ourselves. I think in general we should try not to drift too far from the pact-jvm implementation.

Another option I have seen is requesting of messages via an HTTP proxy: https://github.com/pact-foundation/pact-message-demo (the gist: you add endpoints to the provider to support returning messages based on description and provider state) -- however, pact-jvm does not support this natively.

Improve `PactBrokerWithSelectors` syntax

While updating our internal library to the latest version of pact4s, I've noticed a few things:

  • the syntax for building a ProviderTags is cumbersome when you have multiple tags. In our case, we read tags from configuration, so we get it as a list.
  • it is now much harder to configure PactBrokerWithSelectors dynamically. For example, we use configuration to dynamically enable/disable certain features like pending pacts or WIP pacts. Previously this just meant passing in an Option, but now we have to build the configuration in stages in an immutable way, which results in harder to read and maintain code (example shown below).
  • PublishVerificationResults expects providerTags: List[String] which means we now have to maintain two different ways of generating provider tags since ProviderTags.toList is private

Here is an example of updating our business logic for these changes. This is what we had previously:

lazy val pactSource: PactSource = PactBrokerWithSelectors(
  brokerUrl = pactVerificationSettings.brokerUrl,
  auth = Some(pactVerificationSettings.authentication),
  enablePending = pactVerificationSettings.enablePendingPacts,
  includeWipPactsSince = pactVerificationSettings.includeWorkInProgressPactsSince,
  providerTags = pactVerificationSettings.providerTags.toList,
  selectors = pactVerificationSettings.consumerVersionSelectors
)

And here's what we have now:

lazy val pactSource: PactSource = {
  val pactSource = PactBrokerWithSelectors(pactVerificationSettings.brokerUrl)
    .withAuth(pactVerificationSettings.authentication)
    .withSelectors(pactVerificationSettings.consumerVersionSelectors)

  val pactSourceMaybePending =
    if (pactVerificationSettings.enablePendingPacts)
      pactSource.withPendingPactsEnabled(pactVerificationSettings.providerTags)
    else
      pactSource.withPendingPactsDisabled

  pactVerificationSettings.includeWorkInProgressPactsSince
    .map(pactSourceMaybePending.withWipPactsSince(_, pactVerificationSettings.providerTags))
    .getOrElse(pactSourceMaybePending)
}

In addition to updating pactVerificationSettings.providerTags:

val tags = ... // reads them from configuration
ProviderTags(
  tags.headOption.getOrElse(throw new IllegalArgumentException("At least one provider tag must be set.")),
  tags.tail.toList
)

I understand these changes are to ensure the generated settings are type safe and compatible, but it makes the interface harder to use.

Support multiple providers in a single test

For some cases, it could be nice to support multiple providers in a single test, as what is possible with Pact JVM and JUnit: https://github.com/pact-foundation/pact-jvm/blob/master/consumer/junit/src/test/java/au/com/dius/pact/consumer/junit/pactproviderrule/PactMultiProviderTest.java.

Looking at the code, it seems to me that one way to achieve this would be to provide a new trait similar to BasePactForgerResourcesForPlatform that defines a list of pacts rather than a single one:

trait BasePactForgerResourcesForPlatformMultiProvider[Pact <: BasePact] extends BasePactForgerResources {

  // def pact: Pact
  def pacts: Seq[Pact]

  ...

}

The existing BasePactForgerResourcesForPlatform could actually be inheriting BasePactForgerResourcesForPlatformMultiProvider with a sequence of a single pact to avoid too much code duplication.

Then this could be implemented "on demand" for each test framework (scalatest/munit/weaver).

Any thought on this?

Does pact4s support connection to Pactflow broker on the provider side?

Hi,

I'm currently stuck implementing the verification on the provider side against the pacts published by the consumer on the pactflow broker.
In my code, I've set up the following:

val provider: ProviderInfoBuilder = ProviderInfoBuilder( "PROVIDER_SERVICE_NAME", PactSource.PactBrokerWithSelectors( "https://tray.pactflow.io", ) .withAuth(TokenAuth(Properties.envOrElse("PACTFLOW_READ_WRITE_TOKEN", ""))) .withConsumerVersionSelectors(ConsumerVersionSelectors() .branch(Properties.envOrElse("CONSUMER_BRANCH", "dev"), Some("CONSUMER_SERVICE_NAME"), None) ) ).withHost("localhost") .withPort(port) .withRequestFiltering {...etc

The tests run locally against a file, however when I change it to pactflow and run the tests on the pipeline I'm getting this error:
munit.FailException: /home/runner/work/api-service/api-service/src/pact/scala/../pact/provider/TEST_FILE.scala:59 Call to fetch pacts from Pact Broker failed with an exception 58: test("Verify cluster service pacts successfully") { 59: verifyPacts( 60: publishVerificationResults = Some(PublishVerificationResults("CONSUMER_ID_FROM_PACTFLOW")),

(Some names are edited for company privacy)

With the tests failing in the pipeline but no errors showing on pactflow, it seems like the verification isn't reaching pactflow at all. We're currently stuck in our implementation, so I'd like to know whether there's something missing from the code, or whether it is expected for pact4s not to connect to pactflow.

Thank you for your time

Pact test on class created using @inject is not run

I'm trying to replace an integration test with contract test. So I need to make a real call here.
Below is code of the class that's going to make a call (FraudMlServerClientImpl) note that it has @Inject annotation right after class name.

@Singleton
class FraudMlServerClientImpl @Inject()(
  appConfig: FraudBackofficeConfig,
  ws: WSClient
)(implicit ec: ExecutionContext) extends FraudMlServerClient with HealthCheckable with LazyLogging {

  val clientId = appConfig.fraudMlServerConfig.clientId
  val urls: List[String] = appConfig.fraudMlServerConfig.urls.toList

  val retryPolicy = RetryPolicy(maxAttemptsAllowed = 4)()
  val roundRobin = WeightedRoundRobin[FraudMlServerResource](
      urls.map(u => FraudMlServerResource(u, u, PositiveInt(10000))),
      decrementOnError = _ => Some(10),
      incrementOnSuccess = Some(10)
    )

  def getAllNameNationalityProbability(
    name: String,
    maxResult: Int = 3
  ): Future[Map[String, Double]] = {
    // make a call to another service and receive response
  }

and this is my PactTest.scala where I have only 1 test for testing getAllNameNationalityProbability method
As you can see when I declared my PactTest class, I have @Inject() follow along to provide appConfig and ws which points to server instance I expect to test with pacts .

class PactTest @Inject()(
 appConfig: FraudBackofficeConfig,
 ws: WSClient
) extends AsyncFunSuite with Matchers with RequestResponsePactForger {

  val clientId = 2
  override def pact: RequestResponsePact = ConsumerPactBuilder
    .consumer("FraudBackofficeAPI")
    .hasPactWith("FraudMlAPI")
    .uponReceiving("getAllNameNationalityProbability")
    .path("/predict-nationality")
    .method("POST")
    .headers(
      Map(
        "Content-Type" -> "application/json",
        "ClientId" ->  clientId.toString,
        "RequestId" -> "123e4567-e89b-42d3-a456-556642440000"
      )
    )
    .body(
      """{"name":"John Doe",
        |"maxResult":3}
        |""".stripMargin,
      "application/json"
    )
    .willRespondWith()
    .status(200)
    .body("""{
            |  "ARE": 0.0015790796301290394,
            |  "ARG": 0.0015750796301290393,
            |  "AUS": 0.027795471251010895
            |}
            |""".stripMargin)
    .toPact

  test("getAllNameNationalityProbability should return response for any name") {
    val fraudMlClient = new FraudMlServerClientImpl(appConfig, ws)
    val getNameNat = fraudMlClient.getAllNameNationalityProbability("John Doe")
    assert(getNameNat != null)
  }
}

However, when I execute this command in terminal => sbt "test:testOnly *PactTest"
I got No tests were executed. Seem like it doesn't see a test in this file at all. But when I try removing those @Inject out and initiate client by new FraudMlServerClientImpl(null, null) and execute the same test command again, the test is being run.

The result is not what I expected though, as I said I need to make a real call here. But seem like I can't use @Inject with pact for some what reason. How do I deal with this? please help.

FYI. I'm using
"io.github.jbwheatley" %% "pact4s-scalatest-java8" % "0.0.19" % Test

Be able to define a "before each" / "after each" method for provider state

Unless I missing something, there's no "easy" way to define a beforeEach/afterEach logic to run automatically before or after each contract request verification on the provider side.

Take for instance the following code sample:

class PactVerificationsTest extends PactVerifier {

  override def provider: ProviderInfoBuilder = ProviderInfoBuilder(...)
    ...
    .withStateChangeFunction { 
      case ProviderState("State A", params) =>
         resetState()
         // ... some specific state logic
      case ProviderState("State B", params) =>
         resetState()
         // ... some specific state logic
    }

   ...

}

We have to put the resetState() call in every state.

Would it make sense to have something like a .withStateChangeBeforeHook { f() } that would make the verifier automatically call f() before each request verification?

If you think it make sense, I'll be happy to help implement it.

Remove misleading logging on request/response forger test completion

If the mock server has not received requests for all the interactions defined in the consumer pact, then the pact file will not be written. We are still logging that this write is taking place on the pact4s side, which is misleading in the case that the interactions are not complete. We should check whether all interactions have been run and inform the user accordingly for better transparency.

Saw this come up in #178

ScalaTest: allow invoking custom logic prior to writing pact files

Instead of writing out pacts at the end of run(testName: Option[String], args: Args), it would be more flexible to do it in afterAll(): Unit of the BeforeAndAfterAll trait -- that way users can provide custom logic to fail the tests prior to the pact files being written.

In our case, I want to ensure that a test exists for every message defined. If not, I want the suite to fail and pacts to not be written.

ProviderState is missing params attribute

The documentation and the actual content received by a provider states that a ProviderState is of the form {"state" : "the provider state id string", "params": { "id": "bob" } } but the definition of ProviderState case class is not up to date and only contains the state.

Using Generators

Hello!
I'm not sure if I'm being dense but I can't figure out how to use generators with pact4s on the Provider side of things
Forgive me if I don't use the correct lexicon, I'm super new to pact and inheriting incomplete code

My Consumer generates a pact that contains something like this:

        "generators": {
          "header": {
            "Authorization": {
              "dataType": "STRING",
              "expression": "Bearer ${bearerToken}",
              "type": "ProviderState"
            }
          }
        },
        "headers": {
          "Authorization": "Bearer super-secure"
        },
        "method": "GET",
        "path": "/whatever"
      },

If I understand this correctly, this allows the Provider code to inject its bearerToken to be then used as a param during the contract test, so I expected to be able to return these generated params back in the withStateChangeFunction function but that function is instead a ProviderState => Unit so I can't return anything.

I did some changes locally to pact4s itself and made that function into a ProviderState => ProviderState so I was able to do the injecting I required, but I wanted to engage here first to understand if what I'm doing makes sense, before sending a PR over

Provide a Scala Lambda DSL

From the documentation of Pact (https://docs.pact.io/implementation_guides/jvm/consumer#examples), a new Lambda DSL is available which allows to represent the following data:

[
    ["a1", "a2"],
    [1, 2],
    [{"foo": "Foo"}]
]

With the following syntax (Scala):

newJsonArray((rootArray) => {
    rootArray.array((a) => a.stringValue("a1").stringValue("a2"))
    rootArray.array((a) => a.numberValue(1).numberValue(2))
    rootArray.array((a) => a.object((o) => o.stringValue("foo", "Foo")))
}).build()

Which is quite nice, but there's also a Kotlin Lambda DSL that can express the same with following syntax:

newJsonArray {
    newArray {
      stringValue("a1")
      stringValue("a2")
    }
    newArray {
      numberValue(1)
      numberValue(2)
    }
    newArray {
      newObject { stringValue("foo", "Foo") }
    }
 }

It could be nice to have a Scala Lambda DSL similar to the Kotlin one.

SimpleTimeLimiter exception

In some projects I got exception when use pactVerify method:

java.lang.IllegalAccessError: tried to access method com.google.common.util.concurrent.SimpleTimeLimiter.<init>(Ljava/util/concurrent/ExecutorService;)V from class pact4s.TimeLimiter$

version: 0.5.0

[Verification] How to add header in ProviderResponseBuilder?

Hi,

I have try to add a header in ProviderResponseBuilder with the below code.

    ProviderResponseBuilder(
      responseCode,
      responseBody
    )
      .withHeaders(Map("Content-Type" -> List[String]("application/json;charset=UTF-8")))

However, I got pact verification failed with below error.
scala.collection.immutable.$colon$colon cannot be cast to java.util.List

As I try to debug, it seems the type of Header is different where expected response header type is ArrayList, but the actual response header type is ::.

Any idea how to fix this?

Add support for publishing verification results

Currently you can publish results by manually setting system properties, e.g.

System.setProperty(ProviderVerifier.PACT_VERIFIER_PUBLISH_RESULTS, "true")

But this is clunky and not a common pattern in Scala. It would be preferable to provide an explicit interface for publishing of verification results. Users can still gather information from the System properties if they want to, but they will need to be explicit about it.

Add an example set-up module

Sending people to the test classes to look at examples isn't that user-friendly, and lots there is obfuscated for the purpose of brevity. Would be better to create a module with a full example set up for a request-response relationship, and for a messaging relationship.

Improve state change error message

if the state change function doesn't have a matching case, then the output message will just be something like: State change callback failed with an exception - State Change Request Failed - 400 Bad Request .

It would be much better if we provided more context on why the callback failed, e.g. "expected state "bla bla", received state "blo blo""

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.