Open flexfrank opened 4 years ago
Adding some support on the discussion: HTTP RFC Item 7.2.1 The problem is that seems to change a previous default behavior can be treated as major change.
This is a regression, it should treat it as text/plain
. Although application/octet-stream
is the default in the RFC, we will need to treat it as text to be able to compare it.
Version 4.0.7 has been released with this change
@uglyog
In au.com.dius.pact.core.model.Request
class, application/json
is still default Content-Type
.
My tests throw AssertionError
with 4.0.7 like:
0 - Expected a response type of 'application/json' but the actual type was 'text/plain'
java.lang.AssertionError:
0 - Expected a response type of 'application/json' but the actual type was 'text/plain'
at au.com.dius.pact.provider.junit5.PactVerificationContext.verifyInteraction(PactJUnit5VerificationProvider.kt:85)
This change 4.0.6 -> 4.0.7 resulted that the tests started to fail. The reason is that in the contract there is no content type. before was default was "application/json" now is text/plain which results in a 415 status code. Do you have an idea how you can go around it?
4.0.8 released
I'm having a very similar issue when the response type produced by the mock controller is not a JSON but a text/csv.
I'm using pact-jvm 4.1.6 version.
java.lang.AssertionError:
Failures:
1) Request method
1.1) com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 5 path $
at au.com.dius.pact.provider.spring.target.MockMvcTarget.testInteraction(MockMvcTarget.kt:86)
at au.com.dius.pact.provider.junit.InteractionRunner$interactionBlock$statement$1.evaluate(InteractionRunner.kt:226)
at au.com.dius.pact.provider.junit.RunStateChanges.evaluate(RunStateChanges.kt:30)
at au.com.dius.pact.provider.junit.InteractionRunner.run(InteractionRunner.kt:162)
at au.com.dius.pact.provider.junit.PactRunner.runChild(PactRunner.kt:150)
at au.com.dius.pact.provider.junit.PactRunner.runChild(PactRunner.kt:56)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Any idea how to solve this?
@stardust20 you need to provide the content type of the body if it is not JSON.
I'm sending the accept header, I tried text/plain and text/csv but it doesn't make a difference. The contract in this case looks like the following: Upon receiving:
{
"method": "GET",
"path": "/api/v1/url/csv"
"headers": {
"Accept": "text/csv"
}
And the response that looks as follows:
{
"status": 200,
"headers": {
"Content-Type": "text/csv"
}
"body": "NAME,EMAIL\nSome name, email@email.com\nOther name, otheremail@email.com\n"
}
The method in the controller I'm mocking has the following mapping:
@GetMapping("/api/v1/url/csv", produces = ["text/csv"])
I think the issue here is that the mock controller is not setting up the response content-type, and that causes the error with pact:
MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Content-Disposition:"attachment; filename=csv-file.csv"]
Content type = null
Body = NAME,EMAIL\nSome name, email@email.com\nOther name, otheremail@email.com\n
And then the error:
1.1) com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 5 path $
at au.com.dius.pact.provider.spring.target.MockMvcTarget.testInteraction(MockMvcTarget.kt:86)
at au.com.dius.pact.provider.junit.InteractionRunner$interactionBlock$statement$1.evaluate(InteractionRunner.kt:226)
at au.com.dius.pact.provider.junit.RunStateChanges.evaluate(RunStateChanges.kt:30)
at au.com.dius.pact.provider.junit.InteractionRunner.run(InteractionRunner.kt:162)
at au.com.dius.pact.provider.junit.PactRunner.runChild(PactRunner.kt:150)
at au.com.dius.pact.provider.junit.PactRunner.runChild(PactRunner.kt:56)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
@stardust20 I can't replicate that error. My test works if the controller sets the content type, and fails if it does not. It looks like Springboot is setting the content type to application/json
if the controller does not.
See https://github.com/pact-foundation/pact-jvm/blob/v4.1.x/provider/spring/src/test/java/au/com/dius/pact/provider/spring/BookController.java#L46 and https://github.com/pact-foundation/pact-jvm/blob/v4.1.x/provider/spring/src/test/resources/pacts/readers-contract.json#L82
@stardust20 I can't replicate that error. My test works if the controller sets the content type, and fails if it does not. It looks like Springboot is setting the content type to
application/json
if the controller does not.See https://github.com/pact-foundation/pact-jvm/blob/v4.1.x/provider/spring/src/test/java/au/com/dius/pact/provider/spring/BookController.java#L46 and https://github.com/pact-foundation/pact-jvm/blob/v4.1.x/provider/spring/src/test/resources/pacts/readers-contract.json#L82
My controller had a very similar configuration to that one, with the produces = {"text/csv"}
in the definition but it didn't work. I ended up changing it and adding that part inside the function like response.setHeader("Content-Type"...
I don't understand why it didn't work with the other setup. In any case, thanks for your help!
I test a API that does not have Content-Type header by pact. ProviderClient treats its response body as
application/json
and failed to parse. I think the should be treated asapplication/octet-stream
by default.https://github.com/DiUS/pact-jvm/blob/master/provider/pact-jvm-provider/src/main/kotlin/au/com/dius/pact/provider/ProviderClient.kt#L363-L367