Why can a test not make a callout?
Your deploy ran a test, and that test (or code it calls) tried to send an HTTP or SOAP request. Salesforce blocks that in test context. Salesforce's own wording is short: by default, test methods don't support HTTP callouts, so tests that perform callouts fail (Apex Developer Guide).
In the deployment results it appears as a test failure, not a component failure.
Which code makes the test call out?
- A service class calls
new Http().send(req)and the test calls that class without a mock. This is the usual one. - The test sets a mock, but a different code path makes a second callout the mock does not cover. Check
Test.setMockis called beforeTest.startTest()and that your mock returns something sensible for every endpoint. - The callout hides inside a trigger, a Queueable or a flow-invoked Apex action that the test fires by inserting a record. Nobody reads the test and sees a callout, so nobody adds a mock.
- An older test passed for years because the callout sat behind
if (!Test.isRunningTest()). Someone removed the guard.
Many admins fix this by wrapping the callout in Test.isRunningTest(). We would not. It leaves the callout code untested and the guard tends to get removed later. A mock is the better fix, and one of the top answers on Salesforce Stack Exchange says the same thing (question 31808).
What does the callout failure look like?
A check-only deploy of a class that calls an endpoint, plus a test that asserts on the status code, with --test-level RunSpecifiedTests:
sf project deploy start --dry-run --source-dir force-app \
--test-level RunSpecifiedTests --tests CalloutSvcTest -o my-sandbox
The result came back as Failed with one test failure:
CalloutSvcTest.pingReturns200
Methods defined as TestMethod do not support Web service callouts
How do I fix it in Setup?
In the developer console or your editor:
- Create a mock class that implements
HttpCalloutMockand returns a cannedHttpResponseinrespond. - In the test method, call
Test.setMock(HttpCalloutMock.class, new YourMock());before the code that makes the callout. - Assert on what your code does with the canned response, not on the live service.
- If the test inserts a record before the callout, wrap the DML and the callout in
Test.startTest()andTest.stopTest(). Salesforce has a separate page on doing DML before a mock callout (Apex Developer Guide). - Run the test in the sandbox: Setup > Apex Test Execution > Select Tests, pick the class, Run.
How do I fix it with the CLI?
From the CLI, run it before you deploy:
sf apex run test --class-names CalloutSvcTest --result-format human --wait 10 -o <sandbox-alias>
Then validate again in the target org with a check-only deploy. For a change set, use Validate on the inbound set.
How do I keep callouts from failing deploys?
Make the mock part of the definition of done for any class that calls out. Keep one shared mock class for your most common endpoints so developers do not each write their own. When a new trigger or flow action calls an external system, search the tests that insert that object, because they will start failing too.
If you deploy often, run only the tests that cover your changed classes on the validate step (RunSpecifiedTests) and run the full suite less often. That makes a missing mock fail in minutes, not after a long full-suite run (Metadata API Developer Guide).
Clientell AI finds the tests that cover your bundle and shows the failing line before you approve, so a missing mock does not surprise you in production. See AI Salesforce deployments.
Other test-time failures: coverage below 75%, assertion failed, trigger exception, validation rule in a test.
Questions about web service callouts in tests
Why does the test pass in my sandbox but fail on deploy?
The sandbox run may have used a different test path, or the test class was never run there. A deploy to production runs the tests you specify, or all local tests by default, so a test that nobody ran earlier surfaces then. Run the class by hand in the sandbox first.
Can I just skip the test?
You can exclude the class from RunSpecifiedTests, but production still needs 75% org-wide coverage, so the code has to be covered by something. Fixing the mock is faster than arguing with the coverage number.
Does this apply to SOAP callouts from a WSDL class?
Yes. The same block applies, and the mock interface is WebServiceMock instead of HttpCalloutMock.
Do named credentials change anything?
No. A named credential changes where the endpoint and secret live. The test still cannot call out, so it still needs a mock.