MiKey
07/20/2022, 9:03 PMHeader:
Content-Type: Expected a header 'Content-Type' but was missing
Body:
Expected a response type of 'application/json' but the actual type was 'null'
I have verified that the header is in the contract on the consumer, and that the provider is producing a content-type...any insight what might be going on here?Matt (pactflow.io / pact-js / pact-go)
MiKey
07/21/2022, 3:09 AMMatt (pactflow.io / pact-js / pact-go)
MiKey
07/22/2022, 4:00 PM{
"consumer": {
"name": "partner-signup-fe"
},
"provider": {
"name": "campaign-manager"
},
"interactions": [
{
"description": "a request for campaigns",
"providerState": "list of available campaigns is returned",
"request": {
"method": "GET",
"path": "/"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": [
{
"active": true,
"campaignName": "Campaign Name",
"createdDate": "2022-06-24T17:23:57.232253Z",
"endDate": "2022-06-24T17:23:57.232253Z",
"id": "ce118b6e-d8e1-11e7-9296-cec278b6b50a",
"startDate": "2022-06-24T17:23:57.232253Z",
"updatedBy": "SomeUser",
"updatedDate": "2022-06-24T17:23:57.232253Z"
}
],
"matchingRules": {
"$.body": {
"min": 1
},
"$.body[*].*": {
"match": "type"
},
"$.body[*].active": {
"match": "type"
},
"$.body[*].campaignName": {
"match": "type"
},
"$.body[*].createdDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
},
"$.body[*].endDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
},
"$.body[*].id": {
"match": "regex",
"regex": "^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$"
},
"$.body[*].startDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
},
"$.body[*].updatedBy": {
"match": "type"
},
"$.body[*].updatedDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
}
}
}
},
{
"description": "a request for a campaign that exists",
"providerState": "the campaign is returned",
"request": {
"method": "GET",
"path": "/ce118b6e-d8e1-11e7-9296-cec278b6b50a"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"active": true,
"campaignName": "Campaign Name",
"createdDate": "2022-06-24T17:23:57.232253Z",
"endDate": "2022-06-24T17:23:57.232253Z",
"id": "ce118b6e-d8e1-11e7-9296-cec278b6b50a",
"startDate": "2022-06-24T17:23:57.232253Z",
"updatedBy": "SomeUser",
"updatedDate": "2022-06-24T17:23:57.232253Z"
},
"matchingRules": {
"$.body.active": {
"match": "type"
},
"$.body.campaignName": {
"match": "type"
},
"$.body.createdDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
},
"$.body.endDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
},
"$.body.id": {
"match": "regex",
"regex": "^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$"
},
"$.body.startDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
},
"$.body.updatedBy": {
"match": "type"
},
"$.body.updatedDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
}
}
}
},
{
"description": "a request to create a campaign",
"providerState": "campaign is created",
"request": {
"method": "POST",
"path": "/",
"body": {
"active": true,
"campaignName": "Campaign Name",
"endDate": "2022-06-24T17:23:57.232253Z",
"startDate": "2022-06-24T17:23:57.232253Z",
"updatedBy": "Some User"
}
},
"response": {
"status": 200,
"headers": {},
"body": {
"active": true,
"campaignName": "Campaign Name",
"createdDate": "2022-06-24T17:23:57.232253Z",
"endDate": "2022-06-24T17:23:57.232253Z",
"id": "ce118b6e-d8e1-11e7-9296-cec278b6b50a",
"startDate": "2022-06-24T17:23:57.232253Z",
"updatedBy": "SomeUser",
"updatedDate": "2022-06-24T17:23:57.232253Z"
},
"matchingRules": {
"$.body.active": {
"match": "type"
},
"$.body.campaignName": {
"match": "type"
},
"$.body.createdDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
},
"$.body.endDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
},
"$.body.id": {
"match": "regex",
"regex": "^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$"
},
"$.body.startDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
},
"$.body.updatedBy": {
"match": "type"
},
"$.body.updatedDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
}
}
}
},
{
"description": "a request to update a campaign",
"providerState": "the campaign is updated",
"request": {
"method": "PUT",
"path": "/ce118b6e-d8e1-11e7-9296-cec278b6b50a",
"body": {
"active": true,
"campaignName": "Campaign Name",
"endDate": "2022-06-24T17:23:57.232253Z",
"startDate": "2022-06-24T17:23:57.232253Z",
"updatedBy": "Some User",
"id": "ce118b6e-d8e1-11e7-9296-cec278b6b50a"
}
},
"response": {
"status": 200,
"headers": {},
"body": {
"active": true,
"campaignName": "Campaign Name",
"createdDate": "2022-06-24T17:23:57.232253Z",
"endDate": "2022-06-24T17:23:57.232253Z",
"id": "ce118b6e-d8e1-11e7-9296-cec278b6b50a",
"startDate": "2022-06-24T17:23:57.232253Z",
"updatedBy": "SomeUser",
"updatedDate": "2022-06-24T17:23:57.232253Z"
},
"matchingRules": {
"$.body.active": {
"match": "type"
},
"$.body.campaignName": {
"match": "type"
},
"$.body.createdDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
},
"$.body.endDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
},
"$.body.id": {
"match": "regex",
"regex": "^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$"
},
"$.body.startDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
},
"$.body.updatedBy": {
"match": "type"
},
"$.body.updatedDate": {
"match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
}
}
}
},
{
"description": "a request to delete a campaign",
"providerState": "campaign-manager can delete a campaign",
"request": {
"method": "DELETE",
"path": "/ce118b6e-d8e1-11e7-9296-cec278b6b50a"
},
"response": {
"status": 204,
"headers": {}
}
}
],
"metadata": {
"pactSpecification": {
"version": "2.0.0"
}
}
}
MiKey
07/22/2022, 4:01 PM09:55:42.674 [Test worker] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Detected org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@331d645a
09:55:42.674 [Test worker] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Detected org.springframework.web.servlet.support.SessionFlashMapManager@49b7eb3
09:55:42.674 [Test worker] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
09:55:42.674 [Test worker] INFO org.springframework.test.web.servlet.TestDispatcherServlet - Completed initialization in 2 ms
09:55:42.676 [Test worker] DEBUG au.com.dius.pact.provider.junit5.PactVerificationStateChangeExtension - beforeEach for interaction 'a request for campaigns'
09:55:42.677 [Test worker] INFO au.com.dius.pact.provider.junit5.PactVerificationStateChangeExtension - Invoking state change method 'list of available campaigns is returned':SETUP
Verifying a pact between partner-signup-fe (53d2605be7c514206dfae6909caa2d658f254f5d) and campaign-manager [PENDING]
Notices:
1) The pact at <https://pax8.pactflow.io/pacts/provider/campaign-manager/consumer/partner-signup-fe/pact-version/c719ba4772ec6631e6fb052e8ef165153207b0b6> is being verified because the pact content belongs to the consumer version matching the following criterion:
* latest version of partner-signup-fe that has a pact with campaign-manager (53d2605be7c514206dfae6909caa2d658f254f5d)
2) This pact is in pending state for this version of campaign-manager because a successful verification result for a version of campaign-manager with tag 'local' has not yet been published. If this verification fails, it will not cause the overall build to fail. Read more at <https://docs.pact.io/go/pending>
[from Pact Broker <https://pax8.pactflow.io/pacts/provider/campaign-manager/consumer/partner-signup-fe/pact-version/c719ba4772ec6631e6fb052e8ef165153207b0b6/metadata/c1tdW2xdPXRydWUmc1tdW2N2XT01MTAmcD10cnVl>]
Given list of available campaigns is returned
a request for campaigns
09:55:42.792 [Test worker] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - GET "/", parameters={}
09:55:42.795 [Test worker] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.pax8.campaignmanager.endpoint.CampaignEndpoints#getAllCampaignsByFilter(Optional, Optional, Pageable)
09:55:42.838 [Test worker] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor - Using 'application/json', given [*/*] and supported [application/json]
09:55:42.862 [Test worker] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor - Nothing to write: null body
09:55:42.863 [Test worker] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Completed 200 OK
09:55:42.864 [Test worker] DEBUG au.com.dius.pact.provider.spring.junit5.MockMvcTestTarget - Received response: 200
09:55:42.867 [Test worker] DEBUG au.com.dius.pact.provider.spring.junit5.MockMvcTestTarget - Response: ProviderResponse(statusCode=200, headers={}, contentType=application/json, body=)
09:55:42.876 [Test worker] DEBUG au.com.dius.pact.core.matchers.Matching - matchBody: context=MatchingContext(matchers=MatchingRuleCategory(name=body, matchingRules={$=MatchingRuleGroup(rules=[MinTypeMatcher(min=1)], ruleLogic=AND, cascaded=false), $[*].*=MatchingRuleGroup(rules=[au.com.dius.pact.core.model.matchingrules.TypeMatcher@4c829699], ruleLogic=AND, cascaded=false), $[*].active=MatchingRuleGroup(rules=[au.com.dius.pact.core.model.matchingrules.TypeMatcher@4c829699], ruleLogic=AND, cascaded=false), $[*].campaignName=MatchingRuleGroup(rules=[au.com.dius.pact.core.model.matchingrules.TypeMatcher@4c829699], ruleLogic=AND, cascaded=false), $[*].createdDate=MatchingRuleGroup(rules=[RegexMatcher(regex=^\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d(:?[0-5]\d)?|Z)$, example=null)], ruleLogic=AND, cascaded=false), $[*].endDate=MatchingRuleGroup(rules=[RegexMatcher(regex=^\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d(:?[0-5]\d)?|Z)$, example=null)], ruleLogic=AND, cascaded=false), $[*].id=MatchingRuleGroup(rules=[RegexMatcher(regex=^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$, example=null)], ruleLogic=AND, cascaded=false), $[*].startDate=MatchingRuleGroup(rules=[RegexMatcher(regex=^\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d(:?[0-5]\d)?|Z)$, example=null)], ruleLogic=AND, cascaded=false), $[*].updatedBy=MatchingRuleGroup(rules=[au.com.dius.pact.core.model.matchingrules.TypeMatcher@4c829699], ruleLogic=AND, cascaded=false), $[*].updatedDate=MatchingRuleGroup(rules=[RegexMatcher(regex=^\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d(:?[0-5]\d)?|Z)$, example=null)], ruleLogic=AND, cascaded=false)}), allowUnexpectedKeys=true, pluginConfiguration={})
returns a response which
has status code 200 (OK)
includes headers
"Content-Type" with value "application/json" (FAILED)
has a matching body (FAILED)
Pending Failures:
1) Verifying a pact between partner-signup-fe and campaign-manager - a request for campaigns includes headers "Content-Type" with value "[application/json]"
1.1) header: Expected a header 'Content-Type' but was missing
1.2) body-content-type: Expected a response type of 'application/json' but the actual type was 'null'
09:55:42.886 [Test worker] DEBUG au.com.dius.pact.provider.DefaultTestResultAccumulator - Received test result 'Failed(results=[{attribute=header, description=Expected a header 'Content-Type' but was missing, identifier=Content-Type, interactionId=b1b9d02b26684cf6bf742ad95229d7485b42f006}, {attribute=body-content-type, description=Expected a response type of 'application/json' but the actual type was 'null', interactionId=b1b9d02b26684cf6bf742ad95229d7485b42f006}], description=Headers had differences, Body had differences)' for Pact campaign-manager-partner-signup-fe and a request for campaigns (Pact Broker <https://pax8.pactflow.io/pacts/provider/campaign-manager/consumer/partner-signup-fe/pact-version/c719ba4772ec6631e6fb052e8ef165153207b0b6/metadata/c1tdW2xdPXRydWUmc1tdW2N2XT01MTAmcD10cnVl>)
09:55:42.889 [Test worker] DEBUG au.com.dius.pact.provider.DefaultTestResultAccumulator - Number of interactions #5 and results: [Failed(results=[{attribute=header, description=Expected a header 'Content-Type' but was missing, identifier=Content-Type, interactionId=b1b9d02b26684cf6bf742ad95229d7485b42f006}, {attribute=body-content-type, description=Expected a response type of 'application/json' but the actual type was 'null', interactionId=b1b9d02b26684cf6bf742ad95229d7485b42f006}], description=Headers had differences, Body had differences)]
09:55:42.889 [Test worker] WARN au.com.dius.pact.provider.DefaultTestResultAccumulator - Not all of the 5 were verified. The following were missing:
09:55:42.889 [Test worker] WARN au.com.dius.pact.provider.DefaultTestResultAccumulator - a request for a campaign that exists
09:55:42.889 [Test worker] WARN au.com.dius.pact.provider.DefaultTestResultAccumulator - a request to create a campaign
09:55:42.889 [Test worker] WARN au.com.dius.pact.provider.DefaultTestResultAccumulator - a request to update a campaign
09:55:42.889 [Test worker] WARN au.com.dius.pact.provider.DefaultTestResultAccumulator - a request to delete a campaign
09:55:42.889 [Test worker] DEBUG au.com.dius.pact.provider.junit5.PactVerificationStateChangeExtension - afterEach for interaction 'a request for campaigns'
09:55:42.895 [Test worker] DEBUG _org.springframework.web.servlet.HandlerMapping.Mappings -
c.p.c.e.CampaignEndpoints:
{POST [/], consumes [application/json], produces [application/json]}: createCampaign(CampaignDTO)
{DELETE [/{id}]}: deleteCampaign(String)
{POST [/populate-campaigns]}: populateWithContractorData()
{GET [/], produces [application/json]}: getAllCampaignsByFilter(Optional,Optional,Pageable)
{GET [/{id}], produces [application/json]}: getCampaignById(String)
{PUT [/{id}], consumes [application/json], produces [application/json]}: updatePartner(CampaignDTO,String)
09:55:42.896 [Test worker] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - 6 mappings in org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
09:55:42.900 [Test worker] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - ControllerAdvice beans: 0 @ModelAttribute, 0 @InitBinder, 1 RequestBodyAdvice, 1 ResponseBodyAdvice
09:55:42.901 [Test worker] DEBUG org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - ControllerAdvice beans: 0 @ExceptionHandler, 1 ResponseBodyAdvice
09:55:42.901 [Test worker] INFO org.springframework.mock.web.MockServletContext - Initializing Spring TestDispatcherServlet ''
Matt (pactflow.io / pact-js / pact-go)
contentType
is there in the debug log, whether it’s the expected type or detected, but you can see the headers map is empty)
9:55:42.792 [Test worker] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - GET "/", parameters={}
09:55:42.795 [Test worker] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.pax8.campaignmanager.endpoint.CampaignEndpoints#getAllCampaignsByFilter(Optional, Optional, Pageable)
09:55:42.838 [Test worker] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor - Using 'application/json', given [*/*] and supported [application/json]
09:55:42.862 [Test worker] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor - Nothing to write: null body
09:55:42.863 [Test worker] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Completed 200 OK
09:55:42.864 [Test worker] DEBUG au.com.dius.pact.provider.spring.junit5.MockMvcTestTarget - Received response: 200
09:55:42.867 [Test worker] DEBUG au.com.dius.pact.provider.spring.junit5.MockMvcTestTarget - Response: ProviderResponse(statusCode=200, headers={}, contentType=application/json, body=)
MiKey
07/25/2022, 2:00 AMMiKey
07/25/2022, 2:01 AMMiKey
07/25/2022, 4:56 PM}.andExpect {
status { isOk() }
content { contentType(MediaType.APPLICATION_JSON) }
Matt (pactflow.io / pact-js / pact-go)
uglyog
Matt (pactflow.io / pact-js / pact-go)
uglyog
MiKey
07/28/2022, 8:02 PM@SpringBootTest
to use MockMVC like this? Guessing because I don't is why the header doesn't show there