pact-jvm-consumer-groovy ========================= Groovy DSL for Pact JVM ## Dependency The library is available on maven central using: * group-id = `au.com.dius` * artifact-id = `pact-jvm-consumer-groovy` * version-id = `4.0.x` ## Usage Add the `pact-jvm-consumer-groovy` library to your test class path. This provides a `PactBuilder` class for you to use to define your pacts. For a full example, have a look at the example JUnit `ExampleGroovyConsumerPactTest`. If you are using gradle for your build, add it to your `build.gradle`: dependencies { testCompile 'au.com.dius:pact-jvm-consumer-groovy:4.0.0' } Then create an instance of the `PactBuilder` in your test. ```groovy import au.com.dius.pact.consumer.PactVerificationResult import au.com.dius.pact.consumer.groovy.PactBuilder import groovyx.net.http.RESTClient import org.junit.Test class AliceServiceConsumerPactTest { @Test void "A service consumer side of a pact goes a little something like this"() { def alice_service = new PactBuilder() // Create a new PactBuilder alice_service { serviceConsumer "Consumer" // Define the service consumer by name hasPactWith "Alice Service" // Define the service provider that it has a pact with port 1234 // The port number for the service. It is optional, leave it out to // to use a random one given('there is some good mallory') // defines a provider state. It is optional. uponReceiving('a retrieve Mallory request') // upon_receiving starts a new interaction withAttributes(method: 'get', path: '/mallory') // define the request, a GET request to '/mallory' willRespondWith( // define the response we want returned status: 200, headers: ['Content-Type': 'text/html'], body: '"That is some good Mallory."' ) } // Execute the run method to have the mock server run. // It takes a closure to execute your requests and returns a PactVerificationResult. PactVerificationResult result = alice_service.runTest { def client = new RESTClient('http://localhost:1234/') def alice_response = client.get(path: '/mallory') assert alice_response.status == 200 assert alice_response.contentType == 'text/html' def data = alice_response.data.text() assert data == '"That is some good Mallory."' } assert result == PactVerificationResult.Ok.INSTANCE // This means it is all good } } ``` After running this test, the following pact file is produced: { "provider" : { "name" : "Alice Service" }, "consumer" : { "name" : "Consumer" }, "interactions" : [ { "provider_state" : "there is some good mallory", "description" : "a retrieve Mallory request", "request" : { "method" : "get", "path" : "/mallory", "requestMatchers" : { } }, "response" : { "status" : 200, "headers" : { "Content-Type" : "text/html" }, "body" : "That is some good Mallory.", "responseMatchers" : { } } } ] } ### DSL Methods #### serviceConsumer(String consumer) This names the service consumer for the pact. #### hasPactWith(String provider) This names the service provider for the pact. #### port(int port) Sets the port that the mock server will run on. If not supplied, a random port will be used. #### given(String providerState) Defines a state that the provider needs to be in for the request to succeed. For more info, see https://github.com/realestate-com-au/pact/wiki/Provider-states. Can be called multiple times. #### given(String providerState, Map params) Defines a state that the provider needs to be in for the request to succeed. For more info, see https://github.com/realestate-com-au/pact/wiki/Provider-states. Can be called multiple times, and the params map can contain the data required for the state. #### uponReceiving(String requestDescription) Starts the definition of a of a pact interaction. #### withAttributes(Map requestData) Defines the request for the interaction. The request data map can contain the following: | key | Description | Default Value | |----------------------------|-------------------------------------------|-----------------------------| | method | The HTTP method to use | get | | path | The Path for the request | / | | query | Query parameters as a Map<String, List> | | | headers | Map of key-value pairs for the request headers | | | body | The body of the request. If it is not a string, it will be converted to JSON. Also accepts a PactBodyBuilder. | | | prettyPrint | Boolean value to control if the body is pretty printed. See note on Pretty Printed Bodies below | For the path, header attributes and query parameters (version 2.2.2+ for headers, 3.3.7+ for query parameters), you can use regular expressions to match. You can either provide a regex `Pattern` class or use the `regexp` method to construct a `RegexpMatcher` (you can use any of the defined matcher methods, see DSL methods below). If you use a `Pattern`, or the `regexp` method but don't provide a value, a random one will be generated from the regular expression. This value is used when generating requests. For example: ```groovy .withAttributes(path: ~'/transaction/[0-9]+') // This will generate a random path for requests // or .withAttributes(path: regexp('/transaction/[0-9]+', '/transaction/1234567890')) ``` #### withBody(Closure closure) Constructs the body of the request or response by invoking the supplied closure in the context of a PactBodyBuilder. ##### Pretty Printed Bodies An optional Map can be supplied to control how the body is generated. The option values are available: | Option | Description | |--------|-------------| | mimeType | The mime type of the body. Defaults to `application/json` | | prettyPrint | Boolean value controlling whether to pretty-print the body or not. Defaults to true | If the prettyPrint option is not specified, the bodies will be pretty printed unless the mime type corresponds to one that requires compact bodies. Currently only `application/x-thrift+json` is classed as requiring a compact body. For an example of turning off pretty printing: ```groovy service { uponReceiving('a request') withAttributes(method: 'get', path: '/') withBody(prettyPrint: false) { name 'harry' surname 'larry' } } ``` #### willRespondWith(Map responseData) Defines the response for the interaction. The response data map can contain the following: | key | Description | Default Value | |----------------------------|-------------------------------------------|-----------------------------| | status | The HTTP status code to return | 200 | | headers | Map of key-value pairs for the response headers | | | body | The body of the response. If it is not a string, it will be converted to JSON. Also accepts a PactBodyBuilder. | | | prettyPrint | Boolean value to control if the body is pretty printed. See note on Pretty Printed Bodies above | For the headers (version 2.2.2+), you can use regular expressions to match. You can either provide a regex `Pattern` class or use the `regexp` method to construct a `RegexpMatcher` (you can use any of the defined matcher methods, see DSL methods below). If you use a `Pattern`, or the `regexp` method but don't provide a value, a random one will be generated from the regular expression. This value is used when generating responses. For example: ```groovy .willRespondWith(headers: [LOCATION: ~'/transaction/[0-9]+']) // This will generate a random location value // or .willRespondWith(headers: [LOCATION: regexp('/transaction/[0-9]+', '/transaction/1234567890')]) ``` #### PactVerificationResult runTest(Closure closure) The `runTest` method starts the mock server, and then executes the provided closure. It then returns the pact verification result for the pact run. If you require access to the mock server configuration for the URL, it is passed into the closure, e.g., ```groovy PactVerificationResult result = alice_service.runTest() { mockServer -> def client = new RESTClient(mockServer.url) def alice_response = client.get(path: '/mallory') } ``` ### Note on HTTP clients and persistent connections Some HTTP clients may keep the connection open, based on the live connections settings or if they use a connection cache. This could cause your tests to fail if the client you are testing lives longer than an individual test, as the mock server will be started and shutdown for each test. This will result in the HTTP client connection cache having invalid connections. For an example of this where the there was a failure for every second test, see [Issue #342](https://github.com/DiUS/pact-jvm/issues/342). ### Body DSL For building JSON bodies there is a `PactBodyBuilder` that provides as DSL that includes matching with regular expressions and by types. For a more complete example look at `PactBodyBuilderTest`. For an example: ```groovy service { uponReceiving('a request') withAttributes(method: 'get', path: '/') withBody { name(~/\w+/, 'harry') surname regexp(~/\w+/, 'larry') position regexp(~/staff|contractor/, 'staff') happy(true) } } ``` This will return the following body: ```json { "name": "harry", "surname": "larry", "position": "staff", "happy": true } ``` and add the following matchers: ```json { "$.body.name": {"regex": "\\w+"}, "$.body.surname": {"regex": "\\w+"}, "$.body.position": {"regex": "staff|contractor"} } ``` #### DSL Methods The DSL supports the following matching methods: * regexp(Pattern re, String value = null), regexp(String regexp, String value = null) Defines a regular expression matcher. If the value is not provided, a random one will be generated. * hexValue(String value = null) Defines a matcher that accepts hexidecimal values. If the value is not provided, a random hexidcimal value will be generated. * identifier(def value = null) Defines a matcher that accepts integer values. If the value is not provided, a random value will be generated. * ipAddress(String value = null) Defines a matcher that accepts IP addresses. If the value is not provided, a 127.0.0.1 will be used. * numeric(Number value = null) Defines a matcher that accepts any numerical values. If the value is not provided, a random integer will be used. * integer(def value = null) Defines a matcher that accepts any integer values. If the value is not provided, a random integer will be used. * decimal(def value = null) Defines a matcher that accepts any decimal numbers. If the value is not provided, a random decimal will be used. * timestamp(String pattern = null, def value = null) If pattern is not provided the ISO_DATETIME_FORMAT is used ("yyyy-MM-dd'T'HH:mm:ss") . If the value is not provided, the current date and time is used. * time(String pattern = null, def value = null) If pattern is not provided the ISO_TIME_FORMAT is used ("'T'HH:mm:ss") . If the value is not provided, the current date and time is used. * date(String pattern = null, def value = null) If pattern is not provided the ISO_DATE_FORMAT is used ("yyyy-MM-dd") . If the value is not provided, the current date and time is used. * uuid(String value = null) Defines a matcher that accepts UUIDs. A random one will be generated if no value is provided. * equalTo(def value) Defines an equality matcher that always matches the provided value using `equals`. This is useful for resetting cascading type matchers. * includesStr(def value) Defines a matcher that accepts any value where its string form includes the provided string. * nullValue() Defines a matcher that accepts only null values. * url(String basePath, Object... pathFragments) Defines a matcher for URLs, given the base URL path and a sequence of path fragments. The path fragments could be strings or regular expression matchers. For example: ```groovy url('http://localhost:8080', 'pacticipants', regexp('[^\\/]+', 'Activity%20Service')) ``` Defines a matcher that accepts only null values. #### What if a field matches a matcher name in the DSL? When using the body DSL, if there is a field that matches a matcher name (e.g. a field named 'date') then you can do the following: ```groovy withBody { date = date() } ``` ### Ensuring all items in a list match an example Lots of the time you might not know the number of items that will be in a list, but you want to ensure that the list has a minimum or maximum size and that each item in the list matches a given example. You can do this with the `eachLike`, `minLike` and `maxLike` functions. | function | description | |----------|-------------| | `eachLike()` | Ensure that each item in the list matches the provided example | | `maxLike(integer max)` | Ensure that each item in the list matches the provided example and the list is no bigger than the provided max | | `minLike(integer min)` | Ensure that each item in the list matches the provided example and the list is no smaller than the provided min | For example: ```groovy withBody { users minLike(1) { id identifier name string('Fred') } } ``` This will ensure that the user list is never empty and that each user has an identifier that is a number and a name that is a string. You can specify the number of example items to generate in the array. The default is 1. ```groovy withBody { users minLike(1, 3) { id identifier name string('Fred') } } ``` This will create an example user list with 3 users. The each like matchers have been updated to work with primitive types. ```groovy withBody { permissions eachLike(3, 'GRANT') } ``` will generate the following JSON ```json { "permissions": ["GRANT", "GRANT", "GRANT"] } ``` and matchers ```json { "$.body.permissions": {"match": "type"} } ``` and now you can even get more fancy ```groovy withBody { permissions eachLike(3, regexp(~/\w+/)) permissions2 minLike(2, 3, integer()) permissions3 maxLike(4, 3, ~/\d+/) } ``` You can also match arrays at the root level, for instance, ```groovy withBody PactBodyBuilder.eachLike(regexp(~/\w+/)) ``` or if you have arrays of arrays ```groovy withBody PactBodyBuilder.eachLike([ regexp('[0-9a-f]{8}', 'e8cda07e'), regexp(~/\w+/, 'sony') ]) ``` An `eachArrayLike` method has been added to handle matching of arrays of arrays. ```groovy { answers minLike(1) { questionId string("books") answer eachArrayLike { questionId string("title") answer string("BBBB") } } ``` This will generate an array of arrays for the `answer` attribute. ### Matching any key in a map The DSL has been extended for cases where the keys in a map are IDs. For an example of this, see [#313](https://github.com/DiUS/pact-jvm/issues/313). In this case you can use the `keyLike` method, which takes an example key as a parameter. For example: ```groovy withBody { example { one { keyLike '001', 'value' // key like an id mapped to a value } two { keyLike 'ABC001', regexp('\\w+') // key like an id mapped to a matcher } three { keyLike 'XYZ001', { // key like an id mapped to a closure id identifier() } } four { keyLike '001XYZ', eachLike { // key like an id mapped to an array where each item is matched by the following id identifier() // example } } } } ``` For an example, have a look at [WildcardPactSpec](src/test/au/com/dius/pact/consumer/groovy/WildcardPactSpec.groovy). **NOTE:** The `keyLike` method adds a `*` to the matching path, so the matching definition will be applied to all keys of the map if there is not a more specific matcher defined for a particular key. Having more than one `keyLike` condition applied to a map will result in only one being applied when the pact is verified (probably the last). **Further Note: From version 3.5.22 onwards pacts with wildcards applied to map keys will require the Java system property "pact.matching.wildcard" set to value "true" when the pact file is verified.** ### Matching with an OR The V3 spec allows multiple matchers to be combined using either AND or OR for a value. The main use of this would be to either be able to match a value or a null, or to combine different matchers. For example: ```groovy withBody { valueA and('AB', includeStr('A'), includeStr('B')) // valueA must include both A and B valueB or('100', regex(~/\d+/), nullValue()) // valueB must either match a regular expression or be null valueC or('12345678', regex(~/\d{8}/), regex(~/X\d{13}/)) // valueC must match either 8 or X followed by 13 digits } ``` ## Changing the directory pact files are written to By default, pact files are written to `target/pacts` (or `build/pacts` if you use Gradle), but this can be overwritten with the `pact.rootDir` system property. This property needs to be set on the test JVM as most build tools will fork a new JVM to run the tests. For Gradle, add this to your build.gradle: ```groovy test { systemProperties['pact.rootDir'] = "$buildDir/custom-pacts-directory" } ``` ## Forcing pact files to be overwritten (3.6.5+) By default, when the pact file is written, it will be merged with any existing pact file. To force the file to be overwritten, set the Java system property `pact.writer.overwrite` to `true`. # Publishing your pact files to a pact broker If you use Gradle, you can use the [pact Gradle plugin](https://github.com/DiUS/pact-jvm/tree/master/provider/pact-jvm-provider-gradle#publishing-pact-files-to-a-pact-broker) to publish your pact files. # Pact Specification V3 Version 3 of the pact specification changes the format of pact files in the following ways: * Query parameters are stored in a map form and are un-encoded (see [#66](https://github.com/DiUS/pact-jvm/issues/66) and [#97](https://github.com/DiUS/pact-jvm/issues/97) for information on what this can cause). * Introduces a new message pact format for testing interactions via a message queue. * Multiple provider states can be defined with data parameters. ## Generating V3 spec pact files To have your consumer tests generate V3 format pacts, you can pass an option into the `runTest` method. For example: ```groovy PactVerificationResult result = service.runTest(specificationVersion: PactSpecVersion.V3) { config -> def client = new RESTClient(config.url) def response = client.get(path: '/') } ``` ## Consumer test for a message consumer For testing a consumer of messages from a message queue, the `PactMessageBuilder` class provides a DSL for defining your message expectations. It works in much the same way as the `PactBuilder` class for Request-Response interactions, but will generate a V3 format message pact file. The following steps demonstrate how to use it. ### Step 1 - define the message expectations Create a test that uses the `PactMessageBuilder` to define a message expectation, and then call `run`. This will invoke the given closure with a message for each one defined in the pact. ```groovy def eventStream = new PactMessageBuilder().call { serviceConsumer 'messageConsumer' hasPactWith 'messageProducer' given 'order with id 10000004 exists' expectsToReceive 'an order confirmation message' withMetaData(type: 'OrderConfirmed') // Can define any key-value pairs here withContent(contentType: 'application/json') { type 'OrderConfirmed' audit { userCode 'messageService' } origin 'message-service' referenceId '10000004-2' timeSent: '2015-07-22T10:14:28+00:00' value { orderId '10000004' value '10.000000' fee '10.00' gst '15.00' } } } ``` ### Step 2 - call your message handler with the generated messages This example tests a message handler that gets messages from a Kafka topic. In this case the Pact message is wrapped as a Kafka `MessageAndMetadata`. ```groovy eventStream.run { Message message -> messageHandler.handleMessage(new MessageAndMetadata('topic', 1, new kafka.message.Message(message.contentsAsBytes()), 0, null, valueDecoder)) } ``` ### Step 3 - validate that the message was handled correctly ```groovy def order = orderRepository.getOrder('10000004') assert order.status == 'confirmed' assert order.value == 10.0 ``` ### Step 4 - Publish the pact file If the test was successful, a pact file would have been produced with the message from step 1. # Having values injected from provider state callbacks (3.6.11+) You can have values from the provider state callbacks be injected into most places (paths, query parameters, headers, bodies, etc.). This works by using the V3 spec generators with provider state callbacks that return values. One example of where this would be useful is API calls that require an ID which would be auto-generated by the database on the provider side, so there is no way to know what the ID would be beforehand. The DSL method `fromProviderState` allows you to set an expression that will be parsed with the values returned from the provider states. For the body, you can use the key value instead of an expression. For example, assume that an API call is made to get the details of a user by ID. A provider state can be defined that specifies that the user must be exist, but the ID will be created when the user is created. So we can then define an expression for the path where the ID will be replaced with the value returned from the provider state callback. ```groovy service { given('User harry exists') uponReceiving('a request for user harry') withAttributes(method: 'get', path: fromProviderState('/api/user/${id}', '/api/user/100')) withBody { name(fromProviderState('userName', 'harry')) // looks up the value using the userName key } } ```
bean-mapping is a java bean copy tool.
REST SPI Mappings for SOS Proxy Cache.
Provides a client for jira rest api calls and object mapping.
Ponzu is a collections framework for Java. It has JDK-compatible List, Set and Map implementations with a rich API and set of utility classes that work with any JDK compatible Collections, Arrays, Maps or Strings.
WebJar for @react-google-maps/api
Delivers code automation for projects hosted by the FINOS that build with Apache Maven
Main Orbisgis project
BridgeDb is a framework for finding and mapping equivalent database identifiers. It has many facets: it is both a framework, live services, and are identifier mapping files for genes, proteins, and metabolites.
Eclipse JNoSQL Mapping, Artemis API, to key-value NoSQL databases
Implementations of certain SPIs to provide a core set of functionality for the reference management framework. This includes ExternalReference implementations to reference data held in local files and URLs along with the appropriate translate / publish logic. Implementations in this package are tied only to the API, although certain metadata files such as hibernate mappings are also included where appropriate (these will be silently ignored if using a backing store that is not hibernate based)
A Wicket component for Apache Isis' Wicket viewer to render any collection of entities that implement Locatable in a Google map (gmap3 API)
pact-jvm-consumer-junit ======================= Provides a DSL and a base test class for use with Junit to build consumer tests. ##Dependency The library is available on maven central using: * group-id = `au.com.dius` * artifact-id = `pact-jvm-consumer-junit_2.11` * version-id = `3.0.x` ##Usage ### Using the base ConsumerPactTest To write a pact spec extend ConsumerPactTestMk2. This base class defines the following four methods which must be overridden in your test class. * *providerName:* Returns the name of the API provider that Pact will mock * *consumerName:* Returns the name of the API consumer that we are testing. * *createFragment:* Returns the PactFragment containing the interactions that the test setup using the ConsumerPactBuilder DSL * *runTest:* The actual test run. It receives the URL to the mock server as a parameter. Here is an example: ```java import au.com.dius.pact.consumer.dsl.PactDslWithProvider; import au.com.dius.pact.consumer.exampleclients.ConsumerClient; import au.com.dius.pact.consumer.ConsumerPactTest; import au.com.dius.pact.model.PactFragment; import org.junit.Assert; import java.io.IOException; import java.util.HashMap; import java.util.Map; import static org.junit.Assert.assertEquals; public class ExampleJavaConsumerPactTest extends ConsumerPactTest { @Override protected PactFragment createFragment(PactDslWithProvider builder) { Map<String, String> headers = new HashMap<String, String>(); headers.put("testreqheader", "testreqheadervalue"); return builder .given("test state") // NOTE: Using provider states are optional, you can leave it out .uponReceiving("ExampleJavaConsumerPactTest test interaction") .path("/") .method("GET") .headers(headers) .willRespondWith() .status(200) .headers(headers) .body("{\"responsetest\": true, \"name\": \"harry\"}") .given("test state 2") // NOTE: Using provider states are optional, you can leave it out .uponReceiving("ExampleJavaConsumerPactTest second test interaction") .method("OPTIONS") .headers(headers) .path("/second") .body("") .willRespondWith() .status(200) .headers(headers) .body("") .toFragment(); } @Override protected String providerName() { return "test_provider"; } @Override protected String consumerName() { return "test_consumer"; } @Override protected void runTest(String url) throws IOException { Assert.assertEquals(new ConsumerClient(url).options("/second"), 200); Map expectedResponse = new HashMap(); expectedResponse.put("responsetest", true); expectedResponse.put("name", "harry"); assertEquals(new ConsumerClient(url).getAsMap("/", ""), expectedResponse); assertEquals(new ConsumerClient(url).options("/second"), 200); } } ``` ### Using the Pact JUnit Rule Thanks to [@warmuuh](https://github.com/warmuuh) we have a JUnit rule that simplifies running Pact consumer tests. To use it, create a test class and then add the rule: #### 1. Add the Pact Rule to your test class to represent your provider. ```java @Rule public PactProviderRule mockProvider = new PactProviderRule("test_provider", "localhost", 8080, this); ``` The hostname and port are optional. If left out, it will default to localhost and a random available port. #### 2. Annotate a method with Pact that returns a pact fragment for the provider and consumer ```java @Pact(provider="test_provider", consumer="test_consumer") public PactFragment createFragment(PactDslWithProvider builder) { return builder .given("test state") .uponReceiving("ExampleJavaConsumerPactRuleTest test interaction") .path("/") .method("GET") .willRespondWith() .status(200) .body("{\"responsetest\": true}") .toFragment(); } ``` ##### Versions 3.0.2/2.2.13+ You can leave the provider name out. It will then use the provider name of the first mock provider found. I.e., ```java @Pact(consumer="test_consumer") // will default to the provider name from mockProvider public PactFragment createFragment(PactDslWithProvider builder) { return builder .given("test state") .uponReceiving("ExampleJavaConsumerPactRuleTest test interaction") .path("/") .method("GET") .willRespondWith() .status(200) .body("{\"responsetest\": true}") .toFragment(); } ``` #### 3. Annotate your test method with PactVerification to have it run in the context of the mock server setup with the appropriate pact from step 1 and 2 ```java @Test @PactVerification("test_provider") public void runTest() { Map expectedResponse = new HashMap(); expectedResponse.put("responsetest", true); assertEquals(new ConsumerClient("http://localhost:8080").get("/"), expectedResponse); } ``` ##### Versions 3.0.2/2.2.13+ You can leave the provider name out. It will then use the provider name of the first mock provider found. I.e., ```java @Test @PactVerification public void runTest() { // This will run against mockProvider Map expectedResponse = new HashMap(); expectedResponse.put("responsetest", true); assertEquals(new ConsumerClient("http://localhost:8080").get("/"), expectedResponse); } ``` For an example, have a look at [ExampleJavaConsumerPactRuleTest](src/test/java/au/com/dius/pact/consumer/examples/ExampleJavaConsumerPactRuleTest.java) ### Requiring a test with multiple providers The Pact Rule can be used to test with multiple providers. Just add a rule to the test class for each provider, and then include all the providers required in the `@PactVerification` annotation. For an example, look at [PactMultiProviderTest](src/test/java/au/com/dius/pact/consumer/pactproviderrule/PactMultiProviderTest.java). Note that if more than one provider fails verification for the same test, you will only receive a failure for one of them. Also, to have multiple tests in the same test class, the providers must be setup with random ports (i.e. don't specify a hostname and port). Also, if the provider name is left out of any of the annotations, the first one found will be used (which may not be the first one defined). ### Requiring the mock server to run with HTTPS [versions 3.2.7/2.4.9+] From versions 3.2.7/2.4.9+ the mock server can be started running with HTTPS using a self-signed certificate instead of HTTP. To enable this set the `https` parameter to `true`. E.g.: ```java @Rule public PactProviderRule mockTestProvider = new PactProviderRule("test_provider", "localhost", 8443, true, PactConfig.apply(PactSpecVersion.V2), this); // ^^^^ ``` For an exmaple test doing this, see [PactProviderHttpsTest](src/test/java/au/com/dius/pact/consumer/pactproviderrule/PactProviderHttpsTest.java). **NOTE:** The provider will start handling HTTPS requests using a self-signed certificate. Most HTTP clients will not accept connections to a self-signed server as the certificate is untrusted. You may need to enable insecure HTTPS with your client for this test to work. For an example of how to enable insecure HTTPS client connections with Apache Http Client, have a look at [InsecureHttpsRequest](src/test/java/org/apache/http/client/fluent/InsecureHttpsRequest.java). ### Using the Pact DSL directly Sometimes it is not convenient to use the ConsumerPactTest as it only allows one test per test class. The DSL can be used directly in this case. Example: ```java import au.com.dius.pact.consumer.ConsumerPactBuilder; import au.com.dius.pact.consumer.ConsumerPactTest; import au.com.dius.pact.consumer.PactError; import au.com.dius.pact.consumer.TestRun; import au.com.dius.pact.consumer.VerificationResult; import au.com.dius.pact.consumer.examples.client.ProviderClient; import au.com.dius.pact.model.MockProviderConfig; import au.com.dius.pact.model.PactFragment; import org.junit.Test; import java.io.IOException; import java.util.HashMap; import java.util.Map; import static org.junit.Assert.assertEquals; public class PactTest { @Test public void testPact() { PactFragment pactFragment = ConsumerPactBuilder .consumer("Some Consumer") .hasPactWith("Some Provider") .uponReceiving("a request to say Hello") .path("/hello") .method("POST") .body("{\"name\": \"harry\"}") .willRespondWith() .status(200) .body("{\"hello\": \"harry\"}") .toFragment(); MockProviderConfig config = MockProviderConfig.createDefault(); VerificationResult result = pactFragment.runConsumer(config, new TestRun() { @Override public void run(MockProviderConfig config) { Map expectedResponse = new HashMap(); expectedResponse.put("hello", "harry"); try { assertEquals(new ProviderClient(config.url()).hello("{\"name\": \"harry\"}"), expectedResponse); } catch (IOException e) { throw new RuntimeException(e); } } }); if (result instanceof PactError) { throw new RuntimeException(((PactError)result).error()); } assertEquals(ConsumerPactTest.PACT_VERIFIED, result); } } ``` ### The Pact JUnit DSL The DSL has the following pattern: ```java .consumer("Some Consumer") .hasPactWith("Some Provider") .given("a certain state on the provider") .uponReceiving("a request for something") .path("/hello") .method("POST") .body("{\"name\": \"harry\"}") .willRespondWith() .status(200) .body("{\"hello\": \"harry\"}") .uponReceiving("another request for something") .path("/hello") .method("POST") .body("{\"name\": \"harry\"}") .willRespondWith() .status(200) .body("{\"hello\": \"harry\"}") . . . .toFragment() ``` You can define as many interactions as required. Each interaction starts with `uponReceiving` followed by `willRespondWith`. The test state setup with `given` is a mechanism to describe what the state of the provider should be in before the provider is verified. It is only recorded in the consumer tests and used by the provider verification tasks. ### Building JSON bodies with PactDslJsonBody DSL The body method of the ConsumerPactBuilder can accept a PactDslJsonBody, which can construct a JSON body as well as define regex and type matchers. For example: ```java PactDslJsonBody body = new PactDslJsonBody() .stringType("name") .booleanType("happy") .hexValue("hexCode") .id() .ipAddress("localAddress") .numberValue("age", 100) .timestamp(); ``` #### DSL Matching methods The following matching methods are provided with the DSL. In most cases, they take an optional value parameter which will be used to generate example values (i.e. when returning a mock response). If no example value is given, a random one will be generated. | method | description | |--------|-------------| | string, stringValue | Match a string value (using string equality) | | number, numberValue | Match a number value (using Number.equals)\* | | booleanValue | Match a boolean value (using equality) | | stringType | Will match all Strings | | numberType | Will match all numbers\* | | integerType | Will match all numbers that are integers (both ints and longs)\* | | decimalType | Will match all real numbers (floating point and decimal)\* | | booleanType | Will match all boolean values (true and false) | | stringMatcher | Will match strings using the provided regular expression | | timestamp | Will match string containing timestamps. If a timestamp format is not given, will match an ISO timestamp format | | date | Will match string containing dates. If a date format is not given, will match an ISO date format | | time | Will match string containing times. If a time format is not given, will match an ISO time format | | ipAddress | Will match string containing IP4 formatted address. | | id | Will match all numbers by type | | hexValue | Will match all hexadecimal encoded strings | | uuid | Will match strings containing UUIDs | _\* Note:_ JSON only supports double precision floating point values. Depending on the language implementation, they may parsed as integer, floating point or decimal numbers. #### Ensuring all items in a list match an example (2.2.0+) Lots of the time you might not know the number of items that will be in a list, but you want to ensure that the list has a minimum or maximum size and that each item in the list matches a given example. You can do this with the `arrayLike`, `minArrayLike` and `maxArrayLike` functions. | function | description | |----------|-------------| | `eachLike` | Ensure that each item in the list matches the provided example | | `maxArrayLike` | Ensure that each item in the list matches the provided example and the list is no bigger than the provided max | | `minArrayLike` | Ensure that each item in the list matches the provided example and the list is no smaller than the provided min | For example: ```java DslPart body = new PactDslJsonBody() .minArrayLike("users", 1) .id() .stringType("name") .closeObject() .closeArray(); ``` This will ensure that the users list is never empty and that each user has an identifier that is a number and a name that is a string. __Version 3.2.4/2.4.6+__ You can specify the number of example items to generate in the array. The default is 1. ```java DslPart body = new PactDslJsonBody() .minArrayLike("users", 1, 2) .id() .stringType("name") .closeObject() .closeArray(); ``` This will generate the example body with 2 items in the users list. #### Root level arrays that match all items (version 2.2.11+) If the root of the body is an array, you can create PactDslJsonArray classes with the following methods: | function | description | |----------|-------------| | `arrayEachLike` | Ensure that each item in the list matches the provided example | | `arrayMinLike` | Ensure that each item in the list matches the provided example and the list is no bigger than the provided max | | `arrayMaxLike` | Ensure that each item in the list matches the provided example and the list is no smaller than the provided min | For example: ```java PactDslJsonArray.arrayEachLike() .date("clearedDate", "mm/dd/yyyy", date) .stringType("status", "STATUS") .decimalType("amount", 100.0) .closeObject() ``` This will then match a body like: ```json [ { "clearedDate" : "07/22/2015", "status" : "C", "amount" : 15.0 }, { "clearedDate" : "07/22/2015", "status" : "C", "amount" : 15.0 }, { "clearedDate" : "07/22/2015", "status" : "C", "amount" : 15.0 } ] ``` __Version 3.2.4/2.4.6+__ You can specify the number of example items to generate in the array. The default is 1. #### Matching JSON values at the root (Version 3.2.2/2.4.3+) For cases where you are expecting basic JSON values (strings, numbers, booleans and null) at the root level of the body and need to use matchers, you can use the `PactDslJsonRootValue` class. It has all the DSL matching methods for basic values that you can use. For example: ```java .consumer("Some Consumer") .hasPactWith("Some Provider") .uponReceiving("a request for a basic JSON value") .path("/hello") .willRespondWith() .status(200) .body(PactDslJsonRootValue.integerType()) ``` #### Matching any key in a map (3.3.1/2.5.0+) The DSL has been extended for cases where the keys in a map are IDs. For an example of this, see [#313](https://github.com/DiUS/pact-jvm/issues/313). In this case you can use the `eachKeyLike` method, which takes an example key as a parameter. For example: ```java DslPart body = new PactDslJsonBody() .object("one") .eachKeyLike("001", PactDslJsonRootValue.id(12345L)) // key like an id mapped to a matcher .closeObject() .object("two") .eachKeyLike("001-A") // key like an id where the value is matched by the following example .stringType("description", "Some Description") .closeObject() .closeObject() .object("three") .eachKeyMappedToAnArrayLike("001") // key like an id mapped to an array where each item is matched by the following example .id("someId", 23456L) .closeObject() .closeArray() .closeObject(); ``` For an example, have a look at [WildcardKeysTest](src/test/java/au/com/dius/pact/consumer/WildcardKeysTest.java). **NOTE:** The `eachKeyLike` method adds a `*` to the matching path, so the matching definition will be applied to all keys of the map if there is not a more specific matcher defined for a particular key. Having more than one `eachKeyLike` condition applied to a map will result in only one being applied when the pact is verified (probably the last). ### Matching on paths (version 2.1.5+) You can use regular expressions to match incoming requests. The DSL has a `matchPath` method for this. You can provide a real path as a second value to use when generating requests, and if you leave it out it will generate a random one from the regular expression. For example: ```java .given("test state") .uponReceiving("a test interaction") .matchPath("/transaction/[0-9]+") // or .matchPath("/transaction/[0-9]+", "/transaction/1234567890") .method("POST") .body("{\"name\": \"harry\"}") .willRespondWith() .status(200) .body("{\"hello\": \"harry\"}") ``` ### Matching on headers (version 2.2.2+) You can use regular expressions to match request and response headers. The DSL has a `matchHeader` method for this. You can provide an example header value to use when generating requests and responses, and if you leave it out it will generate a random one from the regular expression. For example: ```java .given("test state") .uponReceiving("a test interaction") .path("/hello") .method("POST") .matchHeader("testreqheader", "test.*value") .body("{\"name\": \"harry\"}") .willRespondWith() .status(200) .body("{\"hello\": \"harry\"}") .matchHeader("Location", ".*/hello/[0-9]+", "/hello/1234") ``` ### Matching on query parameters (version 3.3.7+) You can use regular expressions to match request query parameters. The DSL has a `matchQuery` method for this. You can provide an example value to use when generating requests, and if you leave it out it will generate a random one from the regular expression. For example: ```java .given("test state") .uponReceiving("a test interaction") .path("/hello") .method("POST") .matchQuery("a", "\\d+", "100") .matchQuery("b", "[A-Z]", "X") .body("{\"name\": \"harry\"}") .willRespondWith() .status(200) .body("{\"hello\": \"harry\"}") ``` ## Debugging pact failures When the test runs, Pact will start a mock provider that will listen for requests and match them against the expectations you setup in `createFragment`. If the request does not match, it will return a 500 error response. Each request received and the generated response is logged using [SLF4J](http://www.slf4j.org/). Just enable debug level logging for au.com.dius.pact.consumer.UnfilteredMockProvider. Most failures tend to be mismatched headers or bodies. ## Changing the directory pact files are written to (2.1.9+) By default, pact files are written to `target/pacts`, but this can be overwritten with the `pact.rootDir` system property. This property needs to be set on the test JVM as most build tools will fork a new JVM to run the tests. For Gradle, add this to your build.gradle: ```groovy test { systemProperties['pact.rootDir'] = "$buildDir/pacts" } ``` For maven, use the systemPropertyVariables configuration: ```xml <project> [...] <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.18</version> <configuration> <systemPropertyVariables> <pact.rootDir>some/other/directory</pact.rootDir> <buildDirectory>${project.build.directory}</buildDirectory> [...] </systemPropertyVariables> </configuration> </plugin> </plugins> </build> [...] </project> ``` For SBT: ```scala fork in Test := true, javaOptions in Test := Seq("-Dpact.rootDir=some/other/directory") ``` # Publishing your pact files to a pact broker If you use Gradle, you can use the [pact Gradle plugin](https://github.com/DiUS/pact-jvm/tree/master/pact-jvm-provider-gradle#publishing-pact-files-to-a-pact-broker) to publish your pact files. # Pact Specification V3 Version 3 of the pact specification changes the format of pact files in the following ways: * Query parameters are stored in a map form and are un-encoded (see [#66](https://github.com/DiUS/pact-jvm/issues/66) and [#97](https://github.com/DiUS/pact-jvm/issues/97) for information on what this can cause). * Introduces a new message pact format for testing interactions via a message queue. ## Generating V3 spec pact files (3.1.0+, 2.3.0+) To have your consumer tests generate V3 format pacts, you can set the specification version to V3. If you're using the `ConsumerPactTest` base class, you can override the `getSpecificationVersion` method. For example: ```java @Override protected PactSpecVersion getSpecificationVersion() { return PactSpecVersion.V3; } ``` If you are using the `PactProviderRule`, you can pass the version into the constructor for the rule. ```java @Rule public PactProviderRule mockTestProvider = new PactProviderRule("test_provider", PactSpecVersion.V3, this); ``` ## Consumer test for a message consumer For testing a consumer of messages from a message queue, the `MessagePactProviderRule` rule class works in much the same way as the `PactProviderRule` class for Request-Response interactions, but will generate a V3 format message pact file. For an example, look at [ExampleMessageConsumerTest](https://github.com/DiUS/pact-jvm/blob/master/pact-jvm-consumer-junit%2Fsrc%2Ftest%2Fjava%2Fau%2Fcom%2Fdius%2Fpact%2Fconsumer%2Fv3%2FExampleMessageConsumerTest.java)
Coherent Map Reduce API
pact-jvm-consumer-junit ======================= Provides a DSL and a base test class for use with Junit to build consumer tests. ## Dependency The library is available on maven central using: * group-id = `au.com.dius` * artifact-id = `pact-jvm-consumer-junit` * version-id = `4.0.x` ## Usage ### Using the base ConsumerPactTest To write a pact spec extend ConsumerPactTest. This base class defines the following four methods which must be overridden in your test class. * *providerName:* Returns the name of the API provider that Pact will mock * *consumerName:* Returns the name of the API consumer that we are testing. * *createFragment:* Returns the PactFragment containing the interactions that the test setup using the ConsumerPactBuilder DSL * *runTest:* The actual test run. It receives the URL to the mock server as a parameter. Here is an example: ```java import au.com.dius.pact.consumer.dsl.PactDslWithProvider; import au.com.dius.pact.consumer.exampleclients.ConsumerClient; import au.com.dius.pact.consumer.ConsumerPactTest; import au.com.dius.pact.model.PactFragment; import org.junit.Assert; import java.io.IOException; import java.util.HashMap; import java.util.Map; import static org.junit.Assert.assertEquals; public class ExampleJavaConsumerPactTest extends ConsumerPactTest { @Override protected RequestResponsePact createFragment(PactDslWithProvider builder) { Map<String, String> headers = new HashMap<String, String>(); headers.put("testreqheader", "testreqheadervalue"); return builder .given("test state") // NOTE: Using provider states are optional, you can leave it out .uponReceiving("ExampleJavaConsumerPactTest test interaction") .path("/") .method("GET") .headers(headers) .willRespondWith() .status(200) .headers(headers) .body("{\"responsetest\": true, \"name\": \"harry\"}") .given("test state 2") // NOTE: Using provider states are optional, you can leave it out .uponReceiving("ExampleJavaConsumerPactTest second test interaction") .method("OPTIONS") .headers(headers) .path("/second") .body("") .willRespondWith() .status(200) .headers(headers) .body("") .toPact(); } @Override protected String providerName() { return "test_provider"; } @Override protected String consumerName() { return "test_consumer"; } @Override protected void runTest(MockServer mockServer, PactTestExecutionContext context) throws IOException { Assert.assertEquals(new ConsumerClient(mockServer.getUrl()).options("/second"), 200); Map expectedResponse = new HashMap(); expectedResponse.put("responsetest", true); expectedResponse.put("name", "harry"); assertEquals(new ConsumerClient(mockServer.getUrl()).getAsMap("/", ""), expectedResponse); assertEquals(new ConsumerClient(mockServer.getUrl()).options("/second"), 200); } } ``` ### Using the Pact JUnit Rule Thanks to [@warmuuh](https://github.com/warmuuh) we have a JUnit rule that simplifies running Pact consumer tests. To use it, create a test class and then add the rule: #### 1. Add the Pact Rule to your test class to represent your provider. ```java @Rule public PactProviderRule mockProvider = new PactProviderRule("test_provider", "localhost", 8080, this); ``` The hostname and port are optional. If left out, it will default to 127.0.0.1 and a random available port. You can get the URL and port from the pact provider rule. #### 2. Annotate a method with Pact that returns a pact fragment for the provider and consumer ```java @Pact(provider="test_provider", consumer="test_consumer") public RequestResponsePact createPact(PactDslWithProvider builder) { return builder .given("test state") .uponReceiving("ExampleJavaConsumerPactRuleTest test interaction") .path("/") .method("GET") .willRespondWith() .status(200) .body("{\"responsetest\": true}") .toPact(); } ``` You can leave the provider name out. It will then use the provider name of the first mock provider found. I.e., ```java @Pact(consumer="test_consumer") // will default to the provider name from mockProvider public RequestResponsePact createFragment(PactDslWithProvider builder) { return builder .given("test state") .uponReceiving("ExampleJavaConsumerPactRuleTest test interaction") .path("/") .method("GET") .willRespondWith() .status(200) .body("{\"responsetest\": true}") .toPact(); } ``` #### 3. Annotate your test method with PactVerification to have it run in the context of the mock server setup with the appropriate pact from step 1 and 2 ```java @Test @PactVerification("test_provider") public void runTest() { Map expectedResponse = new HashMap(); expectedResponse.put("responsetest", true); assertEquals(new ConsumerClient(mockProvider.getUrl()).get("/"), expectedResponse); } ``` You can leave the provider name out. It will then use the provider name of the first mock provider found. I.e., ```java @Test @PactVerification public void runTest() { // This will run against mockProvider Map expectedResponse = new HashMap(); expectedResponse.put("responsetest", true); assertEquals(new ConsumerClient("http://localhost:8080").get("/"), expectedResponse); } ``` For an example, have a look at [ExampleJavaConsumerPactRuleTest](src/test/java/au/com/dius/pact/consumer/examples/ExampleJavaConsumerPactRuleTest.java) ### Requiring a test with multiple providers The Pact Rule can be used to test with multiple providers. Just add a rule to the test class for each provider, and then include all the providers required in the `@PactVerification` annotation. For an example, look at [PactMultiProviderTest](src/test/java/au/com/dius/pact/consumer/pactproviderrule/PactMultiProviderTest.java). Note that if more than one provider fails verification for the same test, you will only receive a failure for one of them. Also, to have multiple tests in the same test class, the providers must be setup with random ports (i.e. don't specify a hostname and port). Also, if the provider name is left out of any of the annotations, the first one found will be used (which may not be the first one defined). ### Requiring the mock server to run with HTTPS The mock server can be started running with HTTPS using a self-signed certificate instead of HTTP. To enable this set the `https` parameter to `true`. E.g.: ```java @Rule public PactProviderRule mockTestProvider = new PactProviderRule("test_provider", "localhost", 8443, true, PactSpecVersion.V2, this); // ^^^^ ``` For an example test doing this, see [PactProviderHttpsTest](src/test/java/au/com/dius/pact/consumer/pactproviderrule/PactProviderHttpsTest.java). **NOTE:** The provider will start handling HTTPS requests using a self-signed certificate. Most HTTP clients will not accept connections to a self-signed server as the certificate is untrusted. You may need to enable insecure HTTPS with your client for this test to work. For an example of how to enable insecure HTTPS client connections with Apache Http Client, have a look at [InsecureHttpsRequest](src/test/java/org/apache/http/client/fluent/InsecureHttpsRequest.java). ### Requiring the mock server to run with HTTPS with a keystore The mock server can be started running with HTTPS using a keystore. To enable this set the `https` parameter to `true`, set the keystore path/file, and the keystore's password. E.g.: ```java @Rule public PactProviderRule mockTestProvider = new PactProviderRule("test_provider", "localhost", 8443, true, "/path/to/your/keystore.jks", "your-keystore-password", PactSpecVersion.V2, this); ``` For an example test doing this, see [PactProviderHttpsKeystoreTest](src/test/java/au/com/dius/pact/consumer/pactproviderrule/PactProviderHttpsKeystoreTest.java). ### Setting default expected request and response values If you have a lot of tests that may share some values (like headers), you can setup default values that will be applied to all the expected requests and responses for the tests. To do this, you need to create a method that takes single parameter of the appropriate type (`PactDslRequestWithoutPath` or `PactDslResponse`) and annotate it with the default marker annotation (`@DefaultRequestValues` or `@DefaultResponseValues`). For example: ```java @DefaultRequestValues public void defaultRequestValues(PactDslRequestWithoutPath request) { Map<String, String> headers = new HashMap<String, String>(); headers.put("testreqheader", "testreqheadervalue"); request.headers(headers); } @DefaultResponseValues public void defaultResponseValues(PactDslResponse response) { Map<String, String> headers = new HashMap<String, String>(); headers.put("testresheader", "testresheadervalue"); response.headers(headers); } ``` For an example test that uses these, have a look at [PactProviderWithMultipleFragmentsTest](src/test/java/au/com/dius/pact/consumer/pactproviderrule/PactProviderWithMultipleFragmentsTest.java) ### Note on HTTP clients and persistent connections Some HTTP clients may keep the connection open, based on the live connections settings or if they use a connection cache. This could cause your tests to fail if the client you are testing lives longer than an individual test, as the mock server will be started and shutdown for each test. This will result in the HTTP client connection cache having invalid connections. For an example of this where the there was a failure for every second test, see [Issue #342](https://github.com/DiUS/pact-jvm/issues/342). ### Using the Pact DSL directly Sometimes it is not convenient to use the ConsumerPactTest as it only allows one test per test class. The DSL can be used directly in this case. Example: ```java import au.com.dius.pact.consumer.ConsumerPactBuilder; import au.com.dius.pact.consumer.PactVerificationResult; import au.com.dius.pact.consumer.exampleclients.ProviderClient; import au.com.dius.pact.model.MockProviderConfig; import au.com.dius.pact.model.RequestResponsePact; import org.junit.Test; import java.io.IOException; import java.util.HashMap; import java.util.Map; import static au.com.dius.pact.consumer.ConsumerPactRunnerKt.runConsumerTest; import static org.junit.Assert.assertEquals; /** * Sometimes it is not convenient to use the ConsumerPactTest as it only allows one test per test class. * The DSL can be used directly in this case. */ public class DirectDSLConsumerPactTest { @Test public void testPact() { RequestResponsePact pact = ConsumerPactBuilder .consumer("Some Consumer") .hasPactWith("Some Provider") .uponReceiving("a request to say Hello") .path("/hello") .method("POST") .body("{\"name\": \"harry\"}") .willRespondWith() .status(200) .body("{\"hello\": \"harry\"}") .toPact(); MockProviderConfig config = MockProviderConfig.createDefault(); PactVerificationResult result = runConsumerTest(pact, config, (mockServer, context) -> { Map expectedResponse = new HashMap(); expectedResponse.put("hello", "harry"); try { assertEquals(new ProviderClient(mockServer.getUrl()).hello("{\"name\": \"harry\"}"), expectedResponse); } catch (IOException e) { throw new RuntimeException(e); } }); if (result instanceof PactVerificationResult.Error) { throw new RuntimeException(((PactVerificationResult.Error)result).getError()); } assertEquals(PactVerificationResult.Ok.INSTANCE, result); } } ``` ### The Pact JUnit DSL The DSL has the following pattern: ```java .consumer("Some Consumer") .hasPactWith("Some Provider") .given("a certain state on the provider") .uponReceiving("a request for something") .path("/hello") .method("POST") .body("{\"name\": \"harry\"}") .willRespondWith() .status(200) .body("{\"hello\": \"harry\"}") .uponReceiving("another request for something") .path("/hello") .method("POST") .body("{\"name\": \"harry\"}") .willRespondWith() .status(200) .body("{\"hello\": \"harry\"}") . . . .toPact() ``` You can define as many interactions as required. Each interaction starts with `uponReceiving` followed by `willRespondWith`. The test state setup with `given` is a mechanism to describe what the state of the provider should be in before the provider is verified. It is only recorded in the consumer tests and used by the provider verification tasks. ### Building JSON bodies with PactDslJsonBody DSL **NOTE:** If you are using Java 8, there is [an updated DSL for consumer tests](../pact-jvm-consumer-java8). The body method of the ConsumerPactBuilder can accept a PactDslJsonBody, which can construct a JSON body as well as define regex and type matchers. For example: ```java PactDslJsonBody body = new PactDslJsonBody() .stringType("name") .booleanType("happy") .hexValue("hexCode") .id() .ipAddress("localAddress") .numberValue("age", 100) .timestamp(); ``` #### DSL Matching methods The following matching methods are provided with the DSL. In most cases, they take an optional value parameter which will be used to generate example values (i.e. when returning a mock response). If no example value is given, a random one will be generated. | method | description | |--------|-------------| | string, stringValue | Match a string value (using string equality) | | number, numberValue | Match a number value (using Number.equals)\* | | booleanValue | Match a boolean value (using equality) | | stringType | Will match all Strings | | numberType | Will match all numbers\* | | integerType | Will match all numbers that are integers (both ints and longs)\* | | decimalType | Will match all real numbers (floating point and decimal)\* | | booleanType | Will match all boolean values (true and false) | | stringMatcher | Will match strings using the provided regular expression | | timestamp | Will match string containing timestamps. If a timestamp format is not given, will match an ISO timestamp format | | date | Will match string containing dates. If a date format is not given, will match an ISO date format | | time | Will match string containing times. If a time format is not given, will match an ISO time format | | ipAddress | Will match string containing IP4 formatted address. | | id | Will match all numbers by type | | hexValue | Will match all hexadecimal encoded strings | | uuid | Will match strings containing UUIDs | | includesStr | Will match strings containing the provided string | | equalsTo | Will match using equals | | matchUrl | Defines a matcher for URLs, given the base URL path and a sequence of path fragments. The path fragments could be strings or regular expression matchers | _\* Note:_ JSON only supports double precision floating point values. Depending on the language implementation, they may parsed as integer, floating point or decimal numbers. #### Ensuring all items in a list match an example Lots of the time you might not know the number of items that will be in a list, but you want to ensure that the list has a minimum or maximum size and that each item in the list matches a given example. You can do this with the `arrayLike`, `minArrayLike` and `maxArrayLike` functions. | function | description | |----------|-------------| | `eachLike` | Ensure that each item in the list matches the provided example | | `maxArrayLike` | Ensure that each item in the list matches the provided example and the list is no bigger than the provided max | | `minArrayLike` | Ensure that each item in the list matches the provided example and the list is no smaller than the provided min | For example: ```java DslPart body = new PactDslJsonBody() .minArrayLike("users", 1) .id() .stringType("name") .closeObject() .closeArray(); ``` This will ensure that the users list is never empty and that each user has an identifier that is a number and a name that is a string. You can specify the number of example items to generate in the array. The default is 1. ```java DslPart body = new PactDslJsonBody() .minArrayLike("users", 1, 2) .id() .stringType("name") .closeObject() .closeArray(); ``` This will generate the example body with 2 items in the users list. #### Root level arrays that match all items If the root of the body is an array, you can create PactDslJsonArray classes with the following methods: | function | description | |----------|-------------| | `arrayEachLike` | Ensure that each item in the list matches the provided example | | `arrayMinLike` | Ensure that each item in the list matches the provided example and the list is no bigger than the provided max | | `arrayMaxLike` | Ensure that each item in the list matches the provided example and the list is no smaller than the provided min | For example: ```java PactDslJsonArray.arrayEachLike() .date("clearedDate", "mm/dd/yyyy", date) .stringType("status", "STATUS") .decimalType("amount", 100.0) .closeObject() ``` This will then match a body like: ```json [ { "clearedDate" : "07/22/2015", "status" : "C", "amount" : 15.0 }, { "clearedDate" : "07/22/2015", "status" : "C", "amount" : 15.0 }, { "clearedDate" : "07/22/2015", "status" : "C", "amount" : 15.0 } ] ``` You can specify the number of example items to generate in the array. The default is 1. #### Matching JSON values at the root For cases where you are expecting basic JSON values (strings, numbers, booleans and null) at the root level of the body and need to use matchers, you can use the `PactDslJsonRootValue` class. It has all the DSL matching methods for basic values that you can use. For example: ```java .consumer("Some Consumer") .hasPactWith("Some Provider") .uponReceiving("a request for a basic JSON value") .path("/hello") .willRespondWith() .status(200) .body(PactDslJsonRootValue.integerType()) ``` #### Matching any key in a map The DSL has been extended for cases where the keys in a map are IDs. For an example of this, see [#313](https://github.com/DiUS/pact-jvm/issues/313). In this case you can use the `eachKeyLike` method, which takes an example key as a parameter. For example: ```java DslPart body = new PactDslJsonBody() .object("one") .eachKeyLike("001", PactDslJsonRootValue.id(12345L)) // key like an id mapped to a matcher .closeObject() .object("two") .eachKeyLike("001-A") // key like an id where the value is matched by the following example .stringType("description", "Some Description") .closeObject() .closeObject() .object("three") .eachKeyMappedToAnArrayLike("001") // key like an id mapped to an array where each item is matched by the following example .id("someId", 23456L) .closeObject() .closeArray() .closeObject(); ``` For an example, have a look at [WildcardKeysTest](src/test/java/au/com/dius/pact/consumer/WildcardKeysTest.java). **NOTE:** The `eachKeyLike` method adds a `*` to the matching path, so the matching definition will be applied to all keys of the map if there is not a more specific matcher defined for a particular key. Having more than one `eachKeyLike` condition applied to a map will result in only one being applied when the pact is verified (probably the last). **Further Note: From version 3.5.22 onwards pacts with wildcards applied to map keys will require the Java system property "pact.matching.wildcard" set to value "true" when the pact file is verified.** #### Combining matching rules with AND/OR Matching rules can be combined with AND/OR. There are two methods available on the DSL for this. For example: ```java DslPart body = new PactDslJsonBody() .numberValue("valueA", 100) .and("valueB","AB", PM.includesStr("A"), PM.includesStr("B")) // Must match both matching rules .or("valueC", null, PM.date(), PM.nullValue()) // will match either a valid date or a null value ``` The `and` and `or` methods take a variable number of matchers (varargs). ### Matching on paths You can use regular expressions to match incoming requests. The DSL has a `matchPath` method for this. You can provide a real path as a second value to use when generating requests, and if you leave it out it will generate a random one from the regular expression. For example: ```java .given("test state") .uponReceiving("a test interaction") .matchPath("/transaction/[0-9]+") // or .matchPath("/transaction/[0-9]+", "/transaction/1234567890") .method("POST") .body("{\"name\": \"harry\"}") .willRespondWith() .status(200) .body("{\"hello\": \"harry\"}") ``` ### Matching on headers You can use regular expressions to match request and response headers. The DSL has a `matchHeader` method for this. You can provide an example header value to use when generating requests and responses, and if you leave it out it will generate a random one from the regular expression. For example: ```java .given("test state") .uponReceiving("a test interaction") .path("/hello") .method("POST") .matchHeader("testreqheader", "test.*value") .body("{\"name\": \"harry\"}") .willRespondWith() .status(200) .body("{\"hello\": \"harry\"}") .matchHeader("Location", ".*/hello/[0-9]+", "/hello/1234") ``` ### Matching on query parameters You can use regular expressions to match request query parameters. The DSL has a `matchQuery` method for this. You can provide an example value to use when generating requests, and if you leave it out it will generate a random one from the regular expression. For example: ```java .given("test state") .uponReceiving("a test interaction") .path("/hello") .method("POST") .matchQuery("a", "\\d+", "100") .matchQuery("b", "[A-Z]", "X") .body("{\"name\": \"harry\"}") .willRespondWith() .status(200) .body("{\"hello\": \"harry\"}") ``` ## Debugging pact failures When the test runs, Pact will start a mock provider that will listen for requests and match them against the expectations you setup in `createFragment`. If the request does not match, it will return a 500 error response. Each request received and the generated response is logged using [SLF4J](http://www.slf4j.org/). Just enable debug level logging for au.com.dius.pact.consumer.UnfilteredMockProvider. Most failures tend to be mismatched headers or bodies. ## Changing the directory pact files are written to By default, pact files are written to `target/pacts` (or `build/pacts` if you use Gradle), but this can be overwritten with the `pact.rootDir` system property. This property needs to be set on the test JVM as most build tools will fork a new JVM to run the tests. For Gradle, add this to your build.gradle: ```groovy test { systemProperties['pact.rootDir'] = "$buildDir/custom-pacts-directory" } ``` For maven, use the systemPropertyVariables configuration: ```xml <project> [...] <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.18</version> <configuration> <systemPropertyVariables> <pact.rootDir>some/other/directory</pact.rootDir> <buildDirectory>${project.build.directory}</buildDirectory> [...] </systemPropertyVariables> </configuration> </plugin> </plugins> </build> [...] </project> ``` For SBT: ```scala fork in Test := true, javaOptions in Test := Seq("-Dpact.rootDir=some/other/directory") ``` ### Using `@PactFolder` annotation You can override the directory the pacts are written in a test by adding the `@PactFolder` annotation to the test class. ## Forcing pact files to be overwritten (3.6.5+) By default, when the pact file is written, it will be merged with any existing pact file. To force the file to be overwritten, set the Java system property `pact.writer.overwrite` to `true`. # Publishing your pact files to a pact broker If you use Gradle, you can use the [pact Gradle plugin](../../provider/pact-jvm-provider-gradle#publishing-pact-files-to-a-pact-broker) to publish your pact files. # Pact Specification V3 Version 3 of the pact specification changes the format of pact files in the following ways: * Query parameters are stored in a map form and are un-encoded (see [#66](https://github.com/DiUS/pact-jvm/issues/66) and [#97](https://github.com/DiUS/pact-jvm/issues/97) for information on what this can cause). * Introduces a new message pact format for testing interactions via a message queue. * Multiple provider states can be defined with data parameters. ## Generating V2 spec pact files To have your consumer tests generate V2 format pacts, you can set the specification version to V2. If you're using the `ConsumerPactTest` base class, you can override the `getSpecificationVersion` method. For example: ```java @Override protected PactSpecVersion getSpecificationVersion() { return PactSpecVersion.V2; } ``` If you are using the `PactProviderRule`, you can pass the version into the constructor for the rule. ```java @Rule public PactProviderRule mockTestProvider = new PactProviderRule("test_provider", PactSpecVersion.V2, this); ``` ## Consumer test for a message consumer For testing a consumer of messages from a message queue, the `MessagePactProviderRule` rule class works in much the same way as the `PactProviderRule` class for Request-Response interactions, but will generate a V3 format message pact file. For an example, look at [ExampleMessageConsumerTest](src/test/java/au/com/dius/pact/consumer/v3%2FExampleMessageConsumerTest.java) # Having values injected from provider state callbacks (3.6.11+) You can have values from the provider state callbacks be injected into most places (paths, query parameters, headers, bodies, etc.). This works by using the V3 spec generators with provider state callbacks that return values. One example of where this would be useful is API calls that require an ID which would be auto-generated by the database on the provider side, so there is no way to know what the ID would be beforehand. The following DSL methods all you to set an expression that will be parsed with the values returned from the provider states: For JSON bodies, use `valueFromProviderState`.<br/> For headers, use `headerFromProviderState`.<br/> For query parameters, use `queryParameterFromProviderState`.<br/> For paths, use `pathFromProviderState`. For example, assume that an API call is made to get the details of a user by ID. A provider state can be defined that specifies that the user must be exist, but the ID will be created when the user is created. So we can then define an expression for the path where the ID will be replaced with the value returned from the provider state callback. ```java .pathFromProviderState("/api/users/${id}", "/api/users/100") ``` You can also just use the key instead of an expression: ```java .valueFromProviderState('userId', 'userId', 100) // will look value using userId as the key ```
API for extending squaremap, a minimalistic and lightweight world map viewer for Minecraft servers
Provides a client for jira rest api calls and object mapping.
GWT wrapper for the Google Maps Javascript API V3
This package provides access to posts, topics and forums stored in a PHPBB installation and maps them to the SIOC ontology to represent the information in RDF. This package is experimental, as PHPBB does not provide proper API access over web services. The providers try parsing the HTML content instead.
WorldWind is an open source virtual globe API. WorldWind allows developers to quickly and easily create interactive visualizations of 3D globe, map and geographical information. Organizations around the world use WorldWind to monitor weather patterns, visualize cities and terrain, track vehicle movement, analyze geospatial data and educate humanity about the Earth.
KOMMA is a framework for linked data applications. It supports the management and editing of RDF, RDFS and OWL. It provides Object-Triple-Mapping (comparable to JPA), an editing framework as well as Eclipse RCP and RAP integration.
GWT library to access Google Maps javascript API
GWT library to access Google Maps javascript API
GWT library to access Google Maps javascript API
A clustering library for the Google Maps Android API v2.
A small example of running AtlasMap mapping through runtime API directly
conf4j is a library that simplify configuration access via object to configuration mapping
maps is a simple Spigot plugin and api for creating clientside maps and map screens.
A scalable, concurrent, in-memory Key Value (KV) map. Oak implements a concurrent Key-Value map that can keep all keys and values off-heap. This enables working with bigger heap sizes than JVM's managed heap. OakMap implements an API similar to the industry standard Java8 ConcurrentNavigableMap API. It provides strong (atomic) semantics for read, write, and read-modify-write, as well as (non-atomic) range query (scan) operations, both forward and backward. OakMap is optimized for big keys and values, in particular, for incremental maintenance of objects (update in-place). It is faster and scales better with additional CPU cores than the popular Java ConcurrentNavigableMap ConcurrentSkipListMap
A scalable, concurrent, in-memory Key Value (KV) map. Oak implements a concurrent Key-Value map that can keep all keys and values off-heap. This enables working with bigger heap sizes than JVM's managed heap. OakMap implements an API similar to the industry standard Java8 ConcurrentNavigableMap API. It provides strong (atomic) semantics for read, write, and read-modify-write, as well as (non-atomic) range query (scan) operations, both forward and backward. OakMap is optimized for big keys and values, in particular, for incremental maintenance of objects (update in-place). It is faster and scales better with additional CPU cores than the popular Java ConcurrentNavigableMap ConcurrentSkipListMap
A scalable, concurrent, in-memory Key Value (KV) map. Oak implements a concurrent Key-Value map that can keep all keys and values off-heap. This enables working with bigger heap sizes than JVM's managed heap. OakMap implements an API similar to the industry standard Java8 ConcurrentNavigableMap API. It provides strong (atomic) semantics for read, write, and read-modify-write, as well as (non-atomic) range query (scan) operations, both forward and backward. OakMap is optimized for big keys and values, in particular, for incremental maintenance of objects (update in-place). It is faster and scales better with additional CPU cores than the popular Java ConcurrentNavigableMap ConcurrentSkipListMap
Baidu map api
API for mapping external named queries
RouteDrawer wraps Google Directions API using RxJava for Android so developers can download, parse and draw path on the Google's map in very fast and flexible way.
Layered property map internal API and implementation
Parent project that holds module projects for base classes for persistence like base entity or base business objects and mapper for mapping between them.
AlpineBits is an open standard to exchange touristic data. This library provides functionality to implement AlpineBits server. Use it to build your own standalone AlpineBits server, or integrate parts of it into your existing code base.
Parent project that holds module projects for base classes for persistence like base entity or base business objects and mapper for mapping between them.
Parent project that holds module projects for base classes for persistence like base entity or base business objects and mapper for mapping between them.
The FileVault introduces a JCR repository to filesystem mapping. The mapping is exposed by an API and used by the "FileVault Content Packages" which allow to create portable packages of repository content. The Vault Command Line Interface aka "vlt" provides a subversion like utility to work and develop with repository content. Apache Jackrabbit FileVault is a project of the Apache Software Foundation.
The FileVault introduces a JCR repository to filesystem mapping. The mapping is exposed by an API and used by the "FileVault Content Packages" which allow to create portable packages of repository content. The Vault Command Line Interface aka "vlt" provides a subversion like utility to work and develop with repository content. Apache Jackrabbit FileVault is a project of the Apache Software Foundation.
Maven parent POM for AEM projects that defines a dependency management section containing all of the available dependencies that are provided by the OSGi container.
Parent project that holds module projects for base classes for persistence like base entity or base business objects and mapper for mapping between them.
Web3j Corda RPC and Network Map APIs for the Corda blockchain platform.
API for Apache Phoenix - Hbase Object Relationship mapping library
mapxus-positioning-provider-api
Create the specification in Jakarta EE to help Jakarta EE developers create enterprise-grade applications using Java® and NoSQL technologies. It helps them create scalable applications while maintaining low coupling with the underlying NoSQL technology.
Provides some extra sugar for the machine-generated Java library for Google Maps Engine. https://developers.google.com/api-client-library/java/apis/mapsengine/v1
A place to hold common settings for each module.
Extensions to the Dollar Java API for tuples, Maybe, Lists, and Maps.