Add capability to set provider states for RequestResponsePact. Fixes gh-1740 (#1743)

Co-authored-by: U118971 <U118971@mobi.ch>

fixes gh-1740
This commit is contained in:
Mathieu Amblard
2022-01-03 10:50:30 +01:00
committed by GitHub
parent 03050ce481
commit b14ba2b5b9
5 changed files with 253 additions and 19 deletions

View File

@@ -0,0 +1,93 @@
/*
* Copyright 2013-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.spec.pact;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import au.com.dius.pact.core.model.ProviderState;
import org.springframework.cloud.contract.verifier.util.MetadataUtil;
import org.springframework.cloud.contract.verifier.util.SpringCloudContractMetadata;
import org.springframework.lang.NonNull;
public class PactMetaData implements SpringCloudContractMetadata {
/**
* Key under which this metadata entry can be found in contract's metadata.
*/
public static final String METADATA_KEY = "pact";
/**
* Metadata for adding {@link ProviderState} in Pact contract.
*/
private List<ProviderStateMetadata> providerStates = new ArrayList<>();
public List<ProviderStateMetadata> getProviderStates() {
return this.providerStates;
}
public void setProviderStates(List<ProviderStateMetadata> providerStates) {
this.providerStates = providerStates;
}
@NonNull
public static PactMetaData fromMetadata(Map<String, Object> metadata) {
return MetadataUtil.fromMetadata(metadata, PactMetaData.METADATA_KEY, new PactMetaData());
}
@Override
public String key() {
return METADATA_KEY;
}
@Override
public String description() {
return "Metadata for converting Contract to Pact";
}
/**
* {@link ProviderState} metadata.
*/
public static class ProviderStateMetadata {
/**
* If set, will be added to PACT provider states.
*/
private String name;
private Map<String, Object> params;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Map<String, Object> getParams() {
return this.params;
}
public void setParams(Map<String, Object> params) {
this.params = params;
}
}
}

View File

@@ -21,6 +21,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -30,6 +31,7 @@ import au.com.dius.pact.consumer.dsl.DslPart;
import au.com.dius.pact.consumer.dsl.PactDslRequestWithPath;
import au.com.dius.pact.consumer.dsl.PactDslResponse;
import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
import au.com.dius.pact.consumer.dsl.PactDslWithState;
import au.com.dius.pact.core.model.RequestResponsePact;
import org.apache.commons.lang3.StringUtils;
@@ -107,14 +109,10 @@ class RequestResponsePactCreator {
}
private PactDslRequestWithPath createPactDslRequestWithPath(Contract contract, PactDslResponse pactDslResponse) {
PactDslRequestWithPath pactDslRequest = getPactDslRequest(contract,
getPactDslWithStateFunction(pactDslResponse),
getPactDslRequestWithPathBiFunction(pactDslResponse));
Request request = contract.getRequest();
PactDslRequestWithPath pactDslRequest = pactDslResponse
.uponReceiving(StringUtils.isNotBlank(contract.getDescription()) ? contract.getDescription() : "")
.path(url(request)).method(request.getMethod().getServerValue().toString());
String query = query(request);
if (StringUtils.isNotBlank(query)) {
pactDslRequest = pactDslRequest.encodedQuery(query);
}
final PactDslRequestWithPath finalPactDslRequest = pactDslRequest;
if (request.getHeaders() != null) {
request.getHeaders().getEntries().forEach(h -> processHeader(finalPactDslRequest, h));
@@ -134,23 +132,27 @@ class RequestResponsePactCreator {
return pactDslRequest;
}
private Function<PactMetaData.ProviderStateMetadata, PactDslWithState> getPactDslWithStateFunction(
PactDslResponse pactDslResponse) {
return stateMetadata -> pactDslResponse.given(stateMetadata.getName(), stateMetadata.getParams());
}
private BiFunction<String, Request, PactDslRequestWithPath> getPactDslRequestWithPathBiFunction(
PactDslResponse pactDslResponse) {
return (description, request) -> pactDslResponse.uponReceiving(description).path(url(request))
.method(request.getMethod().getServerValue().toString());
}
private PactDslRequestWithPath createPactDslRequestWithPath(Contract contract,
PactDslWithProvider pactDslWithProvider) {
PactDslRequestWithPath pactDslRequest = getPactDslRequest(contract,
getPactDslWithStateFunction(pactDslWithProvider),
getPactDslRequestWithPathBiFunction(pactDslWithProvider));
Request request = contract.getRequest();
PactDslRequestWithPath pactDslRequest = pactDslWithProvider
.uponReceiving(StringUtils.isNotBlank(contract.getDescription()) ? contract.getDescription() : "")
.path(url(request)).method(request.getMethod().getServerValue().toString());
String query = query(request);
if (StringUtils.isNotBlank(query)) {
pactDslRequest = pactDslRequest.encodedQuery(query);
}
final PactDslRequestWithPath finalPactDslRequest = pactDslRequest;
if (request.getHeaders() != null) {
request.getHeaders().getEntries().forEach(h -> {
processHeader(finalPactDslRequest, h);
});
request.getHeaders().getEntries().forEach(h -> processHeader(finalPactDslRequest, h));
}
if (request.getBody() != null) {
DslPart pactRequestBody = BodyConverter.toPactBody(request.getBody(), DslProperty::getServerValue);
if (request.getBodyMatchers() != null) {
@@ -163,6 +165,57 @@ class RequestResponsePactCreator {
return pactDslRequest;
}
private Function<PactMetaData.ProviderStateMetadata, PactDslWithState> getPactDslWithStateFunction(
PactDslWithProvider pactDslWithProvider) {
return stateMetadata -> pactDslWithProvider.given(stateMetadata.getName(), stateMetadata.getParams());
}
private BiFunction<String, Request, PactDslRequestWithPath> getPactDslRequestWithPathBiFunction(
PactDslWithProvider pactDslWithProvider) {
return (description, request) -> pactDslWithProvider.uponReceiving(description).path(url(request))
.method(request.getMethod().getServerValue().toString());
}
private PactDslRequestWithPath getPactDslRequest(Contract contract,
Function<PactMetaData.ProviderStateMetadata, PactDslWithState> pactDslWithStateFunction,
BiFunction<String, Request, PactDslRequestWithPath> pactDslRequestWithPathBiFunction) {
PactDslWithState pactDslWithState = getPactDslWithState(contract, pactDslWithStateFunction);
String description = StringUtils.isNotBlank(contract.getDescription()) ? contract.getDescription() : "";
Request request = contract.getRequest();
PactDslRequestWithPath pactDslRequest;
if (pactDslWithState != null) {
pactDslRequest = pactDslWithState.uponReceiving(description).path(url(request))
.method(request.getMethod().getServerValue().toString());
}
else {
pactDslRequest = pactDslRequestWithPathBiFunction.apply(description, request);
}
String query = query(request);
if (StringUtils.isNotBlank(query)) {
pactDslRequest = pactDslRequest.encodedQuery(query);
}
return pactDslRequest;
}
private PactDslWithState getPactDslWithState(Contract contract,
Function<PactMetaData.ProviderStateMetadata, PactDslWithState> pactDslWithStateFunction) {
PactDslWithState pactDslWithState = null;
if (contract.getMetadata().containsKey(PactMetaData.METADATA_KEY)) {
PactMetaData metadata = PactMetaData.fromMetadata(contract.getMetadata());
if (!metadata.getProviderStates().isEmpty()) {
for (PactMetaData.ProviderStateMetadata stateMetadata : metadata.getProviderStates()) {
if (pactDslWithState == null) {
pactDslWithState = pactDslWithStateFunction.apply(stateMetadata);
}
else {
pactDslWithState = pactDslWithState.given(stateMetadata.getName(), stateMetadata.getParams());
}
}
}
}
return pactDslWithState;
}
private String url(Request request) {
if (request.getUrlPath() != null) {
return request.getUrlPath().getServerValue().toString();

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2020-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.spec.pact;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import org.assertj.core.api.BDDAssertions;
import org.junit.jupiter.api.Test;
class PactMetaDataTests {
YAMLMapper mapper = new YAMLMapper();
@Test
void should_parse_the_metadata_entry() throws JsonProcessingException {
// @formatter:off
String yamlEntry = ""
+ "pact:\n"
+ " providerStates:\n"
+ " - name: state1\n"
+ " params:\n"
+ " id: 1\n"
+ " value: value1\n"
+ " - name: state2\n"
+ " params:\n"
+ " id: 2\n"
+ " value: value2";
// @formatter:on
PactMetaData metadata = PactMetaData
.fromMetadata(this.mapper.readerForMapOf(Object.class).readValue(yamlEntry));
String serialized = this.mapper.writer().forType(PactMetaData.class).writeValueAsString(metadata);
BDDAssertions.then(serialized).isEqualToNormalizingPunctuationAndWhitespace(yamlEntry.replace("pact:\n", ""));
}
}

View File

@@ -56,4 +56,25 @@ org.springframework.cloud.contract.spec.Contract.make {
contentType('application/json')
}
}
metadata([
pact: [
providerStates:
[
[
name: "someState1",
params: [
id: 1,
value: "someValue1"
]
],
[
name: "someState2",
params: [
id: 2,
value: "someValue2"
]
]
]
]
])
}

View File

@@ -266,7 +266,23 @@
}
}
}
}
},
"providerStates": [
{
"name": "someState1",
"params": {
"id": 1,
"value": "someValue1"
}
},
{
"name": "someState2",
"params": {
"id": 2,
"value": "someValue2"
}
}
]
}
],
"metadata": {