Skip to content

Learn

Real SMS or mocked verification: choose the test for the question

A fixed code checks your application quickly. A real message checks the delivery journey too. Use this coverage map to decide which test belongs in a pull request, staging check, or release gate.

Match coverage to the failure you want to catch

Start with the question behind the test. “Does this form explain an invalid code?” and “Does our staging sender reach a real receiving number?” need different evidence.

Test layerGood evidence forWhat remains outside it
Mocked response in a component or browser testInput rules, loading state, error text, navigationSender configuration, delivery and real message format
Provider's fictional number / fixed OTP modeApplication integration with that provider's test modeActual sending and receipt
Real receiving numberSending path, receipt, extraction, final verificationEvery other destination, region or carrier

Scroll horizontally to see all columns.

Use the cheapest layer that answers the question. A deterministic invalid-code test is valuable even when you also have a real-delivery acceptance test.

Define the real test's finish line

Receiving a text is one checkpoint. The full test also submits its code or link and asserts the application's final state. For sign-in, that might be an authenticated account page. For a phone change, it might be the new verified number in account settings.

Record the inbox position before requesting the message. Use a destination outside any fictional-number mapping. Check that the application is using the sender configuration and environment you intend to cover.

Firebase's documentation describes fictional phone numbers and fixed codes for development. Keep those useful tests, then give real delivery its own destination and test identity.

Place each test where its result is useful

WhenSuggested coverageOwner of a failure
Every change to the formFast mocked success and error statesApplication developer
Auth integration changeProvider test-mode flowAuth integration owner
Sender configuration changeOne real verification journeyApplication and delivery owner
Release or scheduled staging checkReal journey in the environment being checkedRelease / QA owner

Scroll horizontally to see all columns.

Choose cadence from your release risk and delivery cost. A separate real-SMS test lets the team identify an external delivery issue without obscuring an unrelated form regression.

Add one real journey, then expand intentionally

  1. Choose an existing sign-in account or a resettable registration identity.
  2. Assign an independent receiving number and a selected-number credential.
  3. Mark the inbox, request delivery through the app, and wait within a deadline.
  4. Submit the received value and assert the final state.
  5. Classify failure as setup, send, receive, extract or verify.

The Playwright recipe implements this journey. Once it runs locally, use the CI workflow to carry the same test into GitHub Actions.

Questions you may have

Should we remove mocked OTP tests?

Keep them for the states they cover well: malformed input, expired-code messages, resend controls and loading behavior. Add real receipt for delivery confidence. Changing the test layer should follow a coverage gap, rather than a desire to make every test use SMS.

What does a passing real-SMS test prove?

It proves that the tested account, destination, sender configuration and verification step worked in that run. Keep those details with the test result so later failures are comparable. It does not establish universal compatibility with every service or carrier.

Can a provider sandbox prove delivery?

A sandbox or fixed-code mode can prove its documented integration behavior. To establish actual receipt, use a real destination and the provider mode that sends an SMS. Check the provider recipe for the environment-specific setup.