Provider side of PACT using gradle - gradle

I am new to PACT. My application is a spring boot application. Consumer has pact created in PACT broker. Now I am trying to run tests from providers end and I am using gradle plugin to run tests. I have couple of questions:
Pact published by consumer do not have any states specified. So this means I don't have to use any stateChangeUrl at provider side ?
Pact published has get method. However when I run pactVerify server starts and my pact tests are failing because I don't have any existing data. How can I inject data after.
What I am trying to achieve is: When I say pactVerify
Server starts up, and my spring boot app should be up and running in localhost (This is good)
Before pacts are verified I need to inject some data like "POST\add User. So that pact test passes when it tries to do GET\User. (How to do this ?)
Below is my gradle file
pact {
serviceProviders {
'user-api' {
protocol = 'http'
host = 'localhost'
port = 8080
startProviderTask = startService
terminateProviderTask = stopService
if ('pactVerify' in gradle.startParameter.taskNames) {
hasPactsFromPactBroker('http://pactbroker.com') {
< How to write some code here to say do POST before running PACT >
}
}
}
}

Pact published by consumer do not have any states specified. So this means I don't have to use any stateChangeUrl at provider side ?
It means you have chosen not to use this mechanism to change states, and therefore yes, you don't need to use that URL. But you may wish to change your mind on that.
Pact published has get method. However when I run pactVerify server starts and my pact tests are failing because I don't have any existing data. How can I inject data after.
Why not inject the data before you start all of the tests? If you don't have states to worry about, then you may as well just start the provider with the data pre-loaded into the database.
As noted, all of the configuration info can be found at https://github.com/DiUS/pact-jvm/tree/master/pact-jvm-provider-gradle.

The consumer code needs to declare provider states in the pact to allow you to set up the right data for the interaction.
From docs.pact.io
Each interaction in a pact should be verified in isolation, with no context maintained from the previous interactions. Tests that depend on the outcome of previous tests are brittle and land you back in integration test hell, which is the nasty place you're trying to escape by using pacts.
So how do you test a request that requires data to already exist on the provider? Provider states allow you to set up data on the provider by injecting it straight into the data source before the interaction is run, so that it can make a response that matches what the consumer expects. The name of the provider state is specified in the given clause of an interaction in the consumer, and then used to find the block of code to run in the provider to set up the right data. If you need to stub a downstream system, or return an error response that is difficult to cause in the normal scheme of things (e.g. a 500), this is the place where you can set up stubs.
Provider states also allow the consumer to make the same request with different expected responses (e.g. different response codes, or the same resource with a different subset of data).
Keep in mind that a provider state is all about the state of the provider (eg. what data is there, how it is going to handle a given response), not about the state of the consumer, or about what is in the request.
Refer to the the Ruby example to see how this plays out in code.

Related

Contract Testing - Spring Boot Microservices with external SOAP/REST downstream services

We have a set of microservices communicating with each other and some external downstream services. Spring Cloud Contract is used for integration tests to check the service interfaces. I'm able to test the contracts for communication between the microservices.
I'd like to know how to write the contract tests for a producer which
doesn't provide any contracts (cannot access source code)
SOAP-based
Can I impose the contracts from the consumer itself?
Couldn't find the SCC documentation helpful in this regard. Any helpful pointers are appreciated. Thanks!
If it's SOAP based then it's a standard XML based communication. You can generate XML based contracts (an example is here https://docs.spring.io/spring-cloud-contract/docs/current-SNAPSHOT/reference/htmlsingle/#contract-dsl-xml ). Now as for the one where you don't have access to source code, what you can is the following:
You can create a test that will go via a proxy (e.g. WireMock proxy) to the real application and that way you will store that communication in a form of stubs (https://www.youtube.com/watch?v=ZyHG-VOzPZg), you can also check the code (https://github.com/spring-cloud-samples/the-legacy-app/tree/master/stubs_with_proxy). The problem here is that the producer might not be idempotent or may require a lot of concrete setup on the input to get proper response (e.g. a precisely defined date).
You can create contracts on the consumer side, tell stubrunner where they lay (https://docs.spring.io/spring-cloud-contract/docs/current-SNAPSHOT/reference/htmlsingle/#features-stub-runner-stubs-protocol) and turn the generateStubs feature (https://docs.spring.io/spring-cloud-contract/docs/current-SNAPSHOT/reference/htmlsingle/#features-stub-runner-generate-stubs-at-runtime), example of code (https://github.com/spring-cloud-samples/spring-cloud-contract-samples/blob/master/consumer_with_latest_2_2_features/src/test/java/com/example/GenerateStubsTest.java). The problem here is that as a consumer you can write whatever you want and it might not have anything to do with reality. On the other hand you already have the contracts that you could upload to the producer side with a request that they implement their part one day.
It's up to you to decide which one you prefer, bearing in mind that each of the solutions might have its issues.
As for Pact, Pact follows the second approach since it's the consumer that defines how the interaction should look like. That again might have nothing to do with reality.

How to pick only one consumer from pact broker while running provider side tests

I want to pick only one consumer while running my provider side of tests not all the consumers present in PACT hasPactsFromPactBroker('http://pact-broker')
hasPactsFromPactBroker('http://pact-broker')
hasPactWith('scrape-api')
I'm not the pact-jvm maintainer but I believe there is a filter you can use. Have a look in the docs. Otherwise, just give it the URL of the one pact you want to verify. eg http://broker/pacts/provider/PROVIDER/consumer/CONSUMER/latest

Spring cloud stream - integration tests, subscribers don't listen to events

I'm struggling with setting up integration test with spring cloud stream.
let's say I need to test the following integration flow
Create an entity with POST request
publish an event internally with message broker
Collect the event within the same microservice and update the internal read model
Make a GET request to the read model endpoint and check whether the read model has been updated
Updating read model works asynchronously. It works fine while running the app (events get collected and consumed), it does not work when I run integration tests. Method marked with #StreamListener simply does not get called while running tests, app doesn't event connect to message broker (kafka in my case)
I've used spring-cloud-stream-test-support and MessageCollector, but it gives me an opportunity to check whether an event was published and validate its payload.
What I need is to check whether the app has collected the event and reacted correctly to it.
What am I missing? Is there any sort of test binder that app subscribes to during test run?
When using the test binder, the test binder overrides the Kafka binder by default.
To run integration tests in the same project as the unit tests, you have to configure the test to use the real binder by excluding the TestSupportBinderAutoConfiguration.
For global exclusion, see the SCSt docs.
For exclusion in individual tests, see the Boot docs.
Finally, you can also control the list of auto-configuration classes to exclude by using the spring.autoconfigure.exclude property.
e.g. in #TestPropertySource.

Texting existing JMS application

I am working on existing project which uses JMS and spring. I am new to JMS. I need to test that application. My aim is to test that my classes which are used in the application are executed or not.
So can anybody provide me a way in which I can test the application which uses JMS?
I have searched on Google but everyone get started with a sample application. But I want to test my existing application, meaning how my application gets connected with another module. Is there any tool like SOAPUI for JMS test of my existing application, meaning something from which I can execute my classes or listener.
Edit 1
There is a scenario in my project that my module listen a JMS Queue and send SMS or Email to user but actually I am not getting that how my module connected to other module can anybody give me a way so I can find in that direction means which services or APIs used in there.

Reuse jax-ws client proxies for different addresses

I have a bunch of web services servers (around 200) running on the same machine which expose the same service on different ports.
I have a client which perform tasks which include calling the service on different servers.
Something like:
while (true) {
task = readTask();
runHelloService(task.serverAddress)
}
I was wondering what is the best way to generate the HelloService client proxy.
Can I generate one and replace the target address before each call?
Should i generate a client per server (which means 200 client proxies) and use the relevant one?
I will probably want to run the above loop concurrently on several threads.
Currently I have only one proxy which is generated by spring and cxf with the jaxws:client declaration.
This is an interesting use case. I believe that changing the endpoint whilst sharing the proxy amongst multiple threads will not work. There is a one-to-one relationship between a client proxy and a conduit definition. Changes to a conduit are explicitly not thread safe.
I recommend eschewing Spring configuration altogether to create client proxies and instead use programmatic construction of the 200 client proxies.
See also Custom CXF Transport - Simplified Client Workflow.

Resources