Skip to main content

network-tests

Use when writing NetworkRule integration tests in stripe-android — covers testBodyFromFile, inline JSON modification, request matchers, and fixture patterns

Zur Installation springen

Quellinformationen

Repository
stripe/stripe-android
Letzte Quellaktivität
4. September 2026 um 17:15
Erkannte Sprache von SKILL.md
Englisch
Sterne
1.541
Forks
738

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
network-tests
description
Use when writing NetworkRule integration tests in stripe-android — covers testBodyFromFile, inline JSON modification, request matchers, and fixture patterns
# NetworkRule Integration Tests For instrumentation tests that need mocked network responses, use `NetworkRule` (from `network-testing` module) with `testBodyFromFile`. JSON fixture files live in the module's `src/androidTest/resources/` directory (e.g., `paymentsheet/src/androidTest/resources/checkout-session-init.json`) and are resolved by filename from the resources root. ## Basic Structure ```kotlin @RunWith(AndroidJUnit4::class) internal class MyFeatureTest { @get:Rule val testRules: TestRules = TestRules.create() private val networkRule = testRules.networkRule @Test fun testSomething() = runPaymentSheetTest( networkRule = networkRule, resultCallback = ::assertCompleted, ) { testContext -> networkRule.enqueue(requestMatcher) { response -> response.testBodyFromFile("my-fixture.json") } // ... test actions ... } } ``` ## Prefer Inline JSON Modification Over New Fixture Files When a test needs a modified JSON response, use the `testBodyFromFile` lambda to modify the base fixture inline — do NOT create a separate JSON file for each variation. ```kotlin // GOOD: Modify the base fixture inline networkRule.checkoutInit { response -> response.testBodyFromFile("checkout-session-init.json") { json -> json.put("customer_email", "session@example.com") } } // BAD: Creating checkout-session-init-with-email.json with one field different networkRule.checkoutInit { response -> response.testBodyFromFile("checkout-session-init-with-email.json") } ``` This keeps the fixture set minimal and makes the test-specific modifications explicit at the call site. ## Composing Multiple Modifications The lambda receives a `JSONObject` — use standard `org.json` methods to add or modify fields: ```kotlin networkRule.checkoutInit { response -> response.testBodyFromFile("checkout-session-init.json") { json -> json.put("customer", JSONObject(""" { "id": "cus_12345", "payment_methods": [], "can_detach_payment_method": true } """.trimIndent())) json.put("customer_managed_saved_payment_methods_offer_save", JSONObject(""" {"enabled": true, "status": "not_accepted"} """.trimIndent())) } } ``` For nested modifications, chain `getJSONObject()`: ```kotlin response.testBodyFromFile("checkout-session-init.json") { json -> json.getJSONObject("server_built_elements_session_params") .getJSONObject("deferred_intent") .put("setup_future_usage", "off_session") } ``` ## Extracting Shared Modifiers When multiple tests share the same JSON modification, extract the lambda as a parameter: ```kotlin private fun runMyTest( jsonModifier: (JSONObject) -> Unit = {}, ) = runPaymentSheetTest(networkRule = networkRule, resultCallback = ::assertCompleted) { testContext -> networkRule.checkoutInit { response -> response.testBodyFromFile("checkout-session-init.json", jsonModifier) } // ... shared test logic ... } @Test fun testWithSfu() = runMyTest { json -> json.getJSONObject("server_built_elements_session_params") .getJSONObject("deferred_intent") .put("setup_future_usage", "off_session") } ``` ## testBodyFromFile Variants | Signature | Use when | |-----------|----------| | `testBodyFromFile("file.json")` | No modifications needed | | `testBodyFromFile("file.json") { json -> ... }` | Modifying JSON fields inline | | `testBodyFromFile("file.json", replacements)` | String-level find/replace with `ResponseReplacement` | ## Request Matchers Use `RequestMatchers` (from `com.stripe.android.networktesting.RequestMatchers`) to validate request body parameters. Import the matchers you need statically: ```kotlin import com.stripe.android.networktesting.RequestMatchers.bodyPart import com.stripe.android.networktesting.RequestMatchers.hasBodyPart import com.stripe.android.networktesting.RequestMatchers.not networkRule.checkoutConfirm( bodyPart("expected_amount", "5099"), not(hasBodyPart("save_payment_method")), ) { response -> response.testBodyFromFile("checkout-session-confirm.json") } ``` ## Enqueue Responses Next to Their Trigger Enqueue each response immediately before the operation that causes its request. Do not group responses for separate operations at the beginning of a test; doing so obscures which action needs each mock and makes request ordering harder to review. ```kotlin // Initial load request. networkRule.enqueue(consumerLookupMatcher) { response -> response.testBodyFromFile("consumer-session-lookup-success.json") } testContext.launch() // Requests triggered by confirmation and its subsequent refresh. networkRule.checkoutConfirm { response -> response.testBodyFromFile("checkout-session-confirm.json") } networkRule.checkoutInit { response -> response.testBodyFromFile("checkout-session-init.json") } page.clickConfirm() ``` When one user action triggers several requests asynchronously, enqueue all of those responses immediately before that action, keeping them in the same order as the expected requests. ### bodyPart Encoding `bodyPart()`, `hasBodyPart()`, and `query(name, value)` auto-decode both the matcher arguments and the request body before comparing. Use plain readable strings — `urlEncode()` is unnecessary: ```kotlin // Keys with brackets and values with special characters — just use plain strings bodyPart("billing_details[email]", "user@example.com") bodyPart("billing_details[address][line1]", "123 Main St") bodyPart("payment_method_data[allow_redisplay]", "unspecified") // urlEncode() still works (backward compatible) but is unnecessary // bodyPart(urlEncode("billing_details[email]"), urlEncode("user@example.com")) ``` ### Mismatch Debugging When a request doesn't match a mock, the error message shows per-matcher diagnostics with the nearest-miss mock: ``` POST https://localhost/v1/payment_intents/pi_123/confirm Body params: {billing_details[email]=actual@test.com, payment_method=pm_123} Nearest mock: composite(path(/v1/confirm), bodyPart(billing_details[email], expected@test.com)) + PASS: path(/v1/confirm) + PASS: method(POST) - FAIL: bodyPart(billing_details[email], expected@test.com) ``` See `PaymentSheetBillingConfigurationTest.kt` for more examples.
Auf GitHub ansehen