Q21 of 26 · Mobile QA

How do you test in-app purchases and subscriptions without triggering real payment flows?

Mobile QASeniormobilein-app-purchasesubscriptionssandboxiosandroidtesting

Short answer

Short answer: Use Apple's Sandbox environment for iOS (sandbox accounts in TestFlight or Xcode) and Google Play's licence testing for Android (static test responses). For unit and integration tests, inject a mock IAP service to exercise the app's handling of purchased, cancelled, and pending states.

Detail

iOS Sandbox: Apple provides a sandbox IAP environment accessible to debug builds. Create sandbox tester accounts in App Store Connect. When a test account purchases a product, the transaction goes through IAP flow with no real charge. Subscriptions in sandbox renew at accelerated rates (a monthly subscription renews every 5 minutes), making it practical to test renewal and cancellation flows in automated tests.

Google Play Licence Testing: Google provides static test product IDs and test accounts. Test products simulate purchase success, cancellation, and error responses. For Android 12+ you can also use the Play Billing Library's BillingClient test mode.

Mock injection (unit/integration): the most controllable approach. Your IAP service should be an interface — in tests, replace it with a mock implementation that returns predetermined results. This lets you test: (1) how the app responds to a successful purchase (entitlement granted, UI unlocks), (2) how it handles a cancelled purchase (no entitlement, no crash), (3) how it handles a pending purchase (async result — correct for UPI and some debit flows), and (4) how it handles a billing unavailable error.

Integration with Appium: for full E2E flows, use the sandbox/test account in an Appium session. The IAP sheet is a native system sheet — interact with it using accessibility id locators. Be aware that the IAP sheet on iOS cannot be automated directly in some configurations; a workaround is to deep-link straight to the post-purchase state using the sandbox receipt.

// WHAT INTERVIEWERS LOOK FOR

Knows the sandbox environments by name. Distinguishes mock injection (unit, controllable) from sandbox testing (integration, realistic). Mentions the pending state as a distinct case.