Question: Is it possible to use generators in requests?
Nobody has claimed this yet.
- Dominant language
- Swift
- Stars
- 56
- Forks
- 21
- PR merge metrics
- No merged PRs in 30d
Description
❔ Question
I want to use generators in requests like this:
func testSubscription() throws {
mockService
.uponReceiving("Dx subscription")
.given("good state")
.withRequest(
method: PactHTTPMethod.POST,
path: "/api/v1/subscription",
headers: [
"Content-Type": "application/json"
],
body: [
"application": ExampleGenerator.RandomString(size: 20),
"token": ExampleGenerator.RandomString(size: 20),
"applicationVersion": ExampleGenerator.RandomString(size: 20),
"deviceName": ExampleGenerator.RandomString(size: 20),
"platform": ExampleGenerator.RandomString(size: 20),
"platformVersion": ExampleGenerator.RandomString(size: 20),
"language": ExampleGenerator.RandomString(size: 20),
]
)
.willRespondWith(
status: 200,
headers: [
"Content-Type": "application/json"
],
body: Matcher.EachLike(
[
"errors": Matcher.MatchNull(),
"success": Matcher.SomethingLike(true)
],
min: 1
)
)
let request = DxSubscriptionRequest(
application: "com.our.company",
token: "some_token",
applicationVersion: "1.0.0",
deviceName: "iPhone 14 pro",
platform: "iOS",
platformVersion: "16.1",
language: "en"
)
mockService.run { baseURL, done in
let config = APIConfiguration(
baseURL: baseURL,
channel: "",
userAgent: "",
appVersion: request.applicationVersion,
referer: "",
xchannel: "MOBILE_NATIVE_IOS",
token: "",
accountId: "")
let subscription = DxSubscription.request(r: request, config: config)
// Run POST /api/v1/subscription
NetworkClient()
.request(endpoint: subscription) { (response: [DxSubscriptionResponse]?, error) in
guard error == nil else {
XCTFail("Failed with \(String(describing: error))")
done()
return
}
do {
let dxResponse = try XCTUnwrap(response)
XCTAssertNil(dxResponse.first?.errors)
XCTAssertTrue(dxResponse.first?.success ?? false)
} catch {
XCTFail("Expected DxSubscriptionResponse")
}
done()
}
}
}
but the test fails with errors like:
Expected 'RGpibFlTHTnV1ywjejkA' to be equal to 'com.our.company' - Body does not match the expected body definition
To fix that I had to replace
body: [
"application": ExampleGenerator.RandomString(size: 20),
"token": ExampleGenerator.RandomString(size: 20),
"applicationVersion": ExampleGenerator.RandomString(size: 20),
"deviceName": ExampleGenerator.RandomString(size: 20),
"platform": ExampleGenerator.RandomString(size: 20),
"platformVersion": ExampleGenerator.RandomString(size: 20),
"language": ExampleGenerator.RandomString(size: 20),
]
with
"application": Matcher.SomethingLike("string"),
"token": Matcher.SomethingLike("string"),
"applicationVersion": Matcher.SomethingLike("string"),
"deviceName": Matcher.SomethingLike("string"),
"platform": Matcher.SomethingLike("string"),
"platformVersion": Matcher.SomethingLike("string"),
"language": Matcher.SomethingLike("string"),
Is it possible to use generators like in JVM version?
@ExtendWith(PactConsumerTestExt::class)
@PactTestFor(providerName = "dx_provider", pactVersion = PactSpecVersion.V3)
class DxTest {
@Pact(provider = "dx_provider", consumer = "dx_android_consumer")
fun httpInteraction(builder: PactDslWithProvider): RequestResponsePact {
return builder
.given("good state")
.uponReceiving("Dx subscription")
.path("/api/v1/subscription")
.method("POST")
.headers(mapOf("Content-Type" to "application/json"))
.body(
LambdaDsl.newJsonBody { b ->
b.stringType("application")
b.stringType("token")
b.stringType("applicationVersion")
b.stringType("deviceName")
b.stringType("platform")
b.stringType("platformVersion")
b.stringType("language")
}.build()
)
.willRespondWith()
.status(200)
.headers(mapOf("Content-Type" to "application/json"))
.body(
LambdaDsl.newJsonBody { b ->
b.nullValue("errors")
b.booleanType("success", true)
}.build()
)
.toPact()
}
Compare generated pacts:
PactSwift:
"request": {
"body": {
"application": "string",
"applicationVersion": "string",
"deviceName": "string",
"language": "string",
"platform": "string",
"platformVersion": "string",
"token": "string"
},
"headers": {
"Content-Type": "application/json"
},
"matchingRules": {
"body": {
"$.application": {
"combine": "AND",
"matchers": [
{
"match": "type"
}
]
},
...
},
JVM:
"request": {
"body": {
"application": "string",
"applicationVersion": "string",
"deviceName": "string",
"language": "string",
"platform": "string",
"platformVersion": "string",
"token": "string"
},
"generators": {
"body": {
"$.application": {
"size": 20,
"type": "RandomString"
},
"$.applicationVersion": {
"size": 20,
"type": "RandomString"
},
"$.deviceName": {
"size": 20,
"type": "RandomString"
},
"$.language": {
"size": 20,
"type": "RandomString"
},
"$.platform": {
"size": 20,
"type": "RandomString"
},
"$.platformVersion": {
"size": 20,
"type": "RandomString"
},
"$.token": {
"size": 20,
"type": "RandomString"
}
}
},
"headers": {
"Content-Type": "application/json"
},
"matchingRules": {
"body": {
"$.application": {
"combine": "AND",
"matchers": [
{
"match": "type"
}
]
},
...
💬 Context
Xcode 14.2
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Swift request body passed to withRequest and compare the generated PactSwift request with the JVM pact shown in the issue. Trace how matchingRules are produced and determine where the request generators section would need to appear. Done means generated pacts preserve the example body, include the requested RandomString generator entries, and continue matching the actual request.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift
- Domain
- testing-qa
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100