function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
msaz87msaz87 

Methods defined as TestMethod do not support Web service callouts (can't find a solution that works)

I'm receiving the following error during validation/deployment: "Methods defined as TestMethod do not support Web service callouts"

My trigger doesn't contain a callout, but from what I've read it's likely being triggered by a package or another trigger.

I've seen other posts on this subject, and I've tried all their solutions including mocking HTTP responses and callouts, but nothing seems to work. Can anyone help?

Below are the trigger and two classes being deployed:

Trigger
trigger updateContactAfterConverted on Lead (after update) {
        for(Lead lead:System.Trigger.new) {
            
            // was the lead converted?
            if (Lead.IsConverted) {
            
                // query new contact
                Contact newContact = [SELECT Id FROM Contact WHERE Contact.Id = :lead.ConvertedContactId];
                
                // run @future class to update contact after conversion completed
                updateContactAfterConvertedFuture.myMethod(newContact.id);
                
            }
        }
    }

Class referenced in trigger
public class updateContactAfterConvertedFuture {
    
      @future 
      public static void myMethod(String newContact) {
    
        // Find new contact
        Contact updateContact = [SELECT Id FROM Contact WHERE Contact.Id = :newContact LIMIT 1];
        
        // Set field to true                                    
        updateContact.Conversion_Completed__c = TRUE;
                        
        // Update contact                
                        
        update updateContact;     
      
       }
    }
Test class
@isTest
    private class testUpdateContactAfterConverted {
        static testMethod void myUnitTest() {
            // Create new test lead
            Lead myLead = new Lead(LastName = 'Fry', Company='Fry And Sons', LeadSource = 'Advertising', Lead_Source_Detail__c = 'PPC');
            insert myLead;
            
            // Convert test lead
            Database.LeadConvert lc = new Database.LeadConvert();
            lc.setLeadId(myLead.id);
            
            // Check conversion
            LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
            lc.setConvertedStatus(convertStatus.MasterLabel);
            
            // Declare successful
            Database.LeadConvertResult lcr = Database.convertLead(lc);
            System.assert(lcr.isSuccess());
        }
    }
I also tried not including the test class in the deployment, but without it I get 0% code coverage on the trigger.
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri

Hi find this

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restful_http_testing_httpcalloutmock.htm

msaz87msaz87
Hi -- I tried that doc, I copied it exactly as given, except for the CalloutClassTest -- I placed the testCallout() method inside my existing test class, but it didn't work. Any ideas why? Should the CalloutClassTest be separate from the test class for my trigger?
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri
@isTest
public class MockHttpResponseGenerator implements HttpCalloutMock 
{
    public HTTPResponse respond(HTTPRequest req) 
    {

        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/xml');
        res.setBody('Target URL');
        res.setStatusCode(200);
        System.assertEquals('POST', req.getMethod());
      
        return res;
    }
}
 
@isTest
  private class testUpdateContactAfterConverted {
    static testMethod void myUnitTest() {
    // Create new test lead
    Lead myLead = new Lead(LastName = 'Fry', Company='Fry And Sons', LeadSource = 'Advertising', Lead_Source_Detail__c = 'PPC');
    insert myLead;
    
     StaticResourceCalloutMock mock = new StaticResourceCalloutMock();
       mock.setStaticResource('HttpStaticfakeResp');
       mock.setStatusCode(200);
       mock.setHeader('Content-Type', 'application/xml');
       Test.setMock(HttpCalloutMock.class, mock);
       HTTPResponse res =null;
       Test.StartTest();
    // Convert test lead
    Database.LeadConvert lc = new Database.LeadConvert();
    lc.setLeadId(myLead.id);
    
    // Check conversion
    LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
    lc.setConvertedStatus(convertStatus.MasterLabel);
    
    // Declare successful
    Database.LeadConvertResult lcr = Database.convertLead(lc);
    Test.StopTest();
    System.assert(lcr.isSuccess());
    }
  }

Create a Mockresponse generator class and change your test class like what I did
msaz87msaz87
I created the Mock generator class and updated my test class as you showed, but I still receive the same error: "Methods defined as TestMethod do not support Web service callouts"
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri
@isTest
  private class testUpdateContactAfterConverted {
    static testMethod void myUnitTest() {
    // Create new test lead
    Lead myLead = new Lead(LastName = 'Fry', Company='Fry And Sons', LeadSource = 'Advertising', Lead_Source_Detail__c = 'PPC');
    insert myLead;

    
     StaticResourceCalloutMock mock = new StaticResourceCalloutMock();
       mock.setStaticResource('HttpStaticfakeResp');
       mock.setStatusCode(200);
       mock.setHeader('Content-Type', 'application/xml');
       Test.setMock(HttpCalloutMock.class, mock);
       HTTPResponse res =null;
       Test.StartTest();
    // Convert test lead
    Database.LeadConvert lc = new Database.LeadConvert();
    lc.setLeadId(myLead.id);
    
    // Check conversion
    LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
    lc.setConvertedStatus(convertStatus.MasterLabel);
    
    // Declare successful
    Database.LeadConvertResult lcr = Database.convertLead(lc);
    Contact newCOntact = [Select If FROM Contact where Contact.Id =:myLead.ConverttedContactId];
    updateContactAfterConvertedFuture.myMethod(newContact.id);

    Test.StopTest();
    System.assert(lcr.isSuccess());
    }
  }

 
msaz87msaz87
That new test failed, but produced a different error: "System.QueryException: List has no rows for assignment to SObject 
Stack Trace: Class.testUpdateContactAfterConverted.myUnitTest: line 26, column 1"
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri

Database.LeadConvertResult lcr = Database.convertLead(lc);
System.assert(lcr.isSuccess());
if(lcr.isSuccess())
{
Contact newCOntact = [Select If FROM Contact where Id =:myLead.ConverttedContactId];
updateContactAfterConvertedFuture.myMethod(newContact.id);
}
Test.StopTest();

 


 

msaz87msaz87
Same error, different line:
System.QueryException: List has no rows for assignment to SObject 
Stack Trace: Class.testUpdateContactAfterConverted.myUnitTest: line 29, column 1
Test now looks like this:
@isTest
  private class testUpdateContactAfterConverted {
    static testMethod void myUnitTest() {
    // Create new test lead
    Lead myLead = new Lead(LastName = 'Fry', Company='Fry And Sons', LeadSource = 'Advertising', Lead_Source_Detail__c = 'PPC');
    insert myLead;

    
     StaticResourceCalloutMock mock = new StaticResourceCalloutMock();
       mock.setStaticResource('HttpStaticfakeResp');
       mock.setStatusCode(200);
       mock.setHeader('Content-Type', 'application/xml');
       Test.setMock(HttpCalloutMock.class, mock);
       HTTPResponse res =null;
       Test.StartTest();
    // Convert test lead
    Database.LeadConvert lc = new Database.LeadConvert();
    lc.setLeadId(myLead.id);
    
    // Check conversion
    LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
    lc.setConvertedStatus(convertStatus.MasterLabel);
    
    // Declare successful
	Database.LeadConvertResult lcr = Database.convertLead(lc);
	System.assert(lcr.isSuccess());
	if(lcr.isSuccess())
	{
	Contact newContact = [Select Id FROM Contact where Id =:myLead.ConvertedContactId];
	updateContactAfterConvertedFuture.myMethod(newContact.id);
	}
	Test.StopTest();    

    }
  }
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri

one line 29 just query for contact

Contact newContact = [Select Id from Contact LIMIT 1];

Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri
I wonder why the contact is not getting created even after lead is conversion is successful. If you deliberately want to pass the test just create a dummy contact and send that id in updateContactAfterConvertedFuture.mymethod(dummycontact.Id) but that is not good practice 
msaz87msaz87
I modified the class on line 29 and now we're back to the original error:
Methods defined as TestMethod do not support Web service callouts 
Stack Trace: null
Test class:
@isTest
  private class testUpdateContactAfterConverted {
    static testMethod void myUnitTest() {
    // Create new test lead
    Lead myLead = new Lead(LastName = 'Fry', Company='Fry And Sons', LeadSource = 'Advertising', Lead_Source_Detail__c = 'PPC');
    insert myLead;

    
     StaticResourceCalloutMock mock = new StaticResourceCalloutMock();
       mock.setStaticResource('HttpStaticfakeResp');
       mock.setStatusCode(200);
       mock.setHeader('Content-Type', 'application/xml');
       Test.setMock(HttpCalloutMock.class, mock);
       HTTPResponse res =null;
       Test.StartTest();
    // Convert test lead
    Database.LeadConvert lc = new Database.LeadConvert();
    lc.setLeadId(myLead.id);
    
    // Check conversion
    LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
    lc.setConvertedStatus(convertStatus.MasterLabel);
    
    // Declare successful
	Database.LeadConvertResult lcr = Database.convertLead(lc);
	System.assert(lcr.isSuccess());
	if(lcr.isSuccess())
	{
	Contact newContact = [Select Id from Contact LIMIT 1];
	updateContactAfterConvertedFuture.myMethod(newContact.id);
	}
	Test.StopTest();    

    }
  }


 
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri

Sorry I thought that is httpcallout

Please refer this https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts_wsdl2apex_testing.htm

msaz87msaz87
I got the same error: 
Methods defined as TestMethod do not support Web service callouts 
Stack Trace: null

Here's the updated test:
@isTest
  private class testUpdateContactAfterConverted {
    static testMethod void myUnitTest() {
    	
 // This causes a fake response to be generated
        Test.setMock(WebServiceMock.class, new WebServiceMockImpl());
        
        // Call the method that invokes a callout
        String output = WebSvcCallout.callEchoString('Hello World!');
        
        // Verify that a fake result is returned
        System.assertEquals('Mock response', output);    	

	Test.StartTest();
    	
    // Create new test lead
    Lead myLead = new Lead(LastName = 'Fry', Company='Fry And Sons', LeadSource = 'Advertising', Lead_Source_Detail__c = 'PPC');
    insert myLead;

    // Convert test lead
    Database.LeadConvert lc = new Database.LeadConvert();
    lc.setLeadId(myLead.id);
    
    // Check conversion
    LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
    lc.setConvertedStatus(convertStatus.MasterLabel);
    
    // Declare successful
	Database.LeadConvertResult lcr = Database.convertLead(lc);
	System.assert(lcr.isSuccess());
	if(lcr.isSuccess())
	{
	Contact newContact = [Select Id from Contact LIMIT 1];
	updateContactAfterConvertedFuture.myMethod(newContact.id);
	}
	Test.StopTest();    

    }
  }
And per your link I added three more classes:
@isTest
global class WebServiceMockImpl implements WebServiceMock {
   global void doInvoke(
           Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType) {
       docSample.EchoStringResponse_element respElement = 
           new docSample.EchoStringResponse_element();
       respElement.EchoStringResult = 'Mock response';
       response.put('response_x', respElement); 
   }
}
public class WebSvcCallout {
    public static String callEchoString(String input) {
        docSample.DocSamplePort sample = new docSample.DocSamplePort();
        sample.endpoint_x = 'http://api.salesforce.com/foo/bar';
        
        // This invokes the EchoString method in the generated class
        String echo = sample.EchoString(input);
        
        return echo;
    }   
}
public class docSample {
    public class EchoStringResponse_element {
        public String EchoStringResult;
        private String[] EchoStringResult_type_info = new String[]{
                            'EchoStringResult',
                            'http://doc.sample.com/docSample',
                             null,'0','1','false'};
        private String[] apex_schema_type_info = new String[]{
                             'http://doc.sample.com/docSample',
                             'true','false'};
        private String[] field_order_type_info = new String[]{
                             'EchoStringResult'};
    }
    public class EchoString_element {
        public String input;
        private String[] input_type_info = new String[]{
                              'input',
                              'http://doc.sample.com/docSample',
                               null,'0','1','false'};
        private String[] apex_schema_type_info = new String[]{
                               'http://doc.sample.com/docSample',
                               'true','false'};
        private String[] field_order_type_info = new String[]{'input'};
    }
    public class DocSamplePort {
        public String endpoint_x = 'http://YourServer/YourService';
        public Map<String,String> inputHttpHeaders_x;
        public Map<String,String> outputHttpHeaders_x;
        public String clientCertName_x;
        public String clientCert_x;
        public String clientCertPasswd_x;
        public Integer timeout_x;
        private String[] ns_map_type_info = new String[]{
                          'http://doc.sample.com/docSample', 'docSample'};
        public String EchoString(String input) {
            docSample.EchoString_element request_x = new 
                                           docSample.EchoString_element();
            request_x.input = input;
            docSample.EchoStringResponse_element response_x;
            Map<String, docSample.EchoStringResponse_element> response_map_x = 
                       new Map<String, docSample.EchoStringResponse_element>();
            response_map_x.put('response_x', response_x);
            WebServiceCallout.invoke(
              this,
              request_x,
              response_map_x,
              new String[]{endpoint_x,
              'urn:dotnet.callouttest.soap.sforce.com/EchoString',
              'http://doc.sample.com/docSample',
              'EchoString',
              'http://doc.sample.com/docSample',
              'EchoStringResponse',
              'docSample.EchoStringResponse_element'}
            );
            response_x = response_map_x.get('response_x');
            return response_x.EchoStringResult;
        }
    }
}

 
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri
Please don't use same code apply that model to your future class
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri
docsample is not at all useful, instead of doc sample class use you updateContactAfterConvertedFuture.class in code
msaz87msaz87
Sorry, I don't fully understand. Do I not need classes WebServiceMockImpl, WebSvcCallout and docSample?
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri

docsample and WebSvcCallout are sample classes they gave that class just for understanding, our class is updateContactAfterConvertedFuture.....

so please remove those 2 classes and use updatecontactafterconverted class in WebServiceMockImpl 

msaz87msaz87
I'm still a little confused because WebServiceMockImpl references multiple classes within docSample (bolded below):
@isTest
global class WebServiceMockImpl implements WebServiceMock {
   global void doInvoke(
           Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType) {
       docSample.EchoStringResponse_element respElement = 
           new docSample.EchoStringResponse_element();
       respElement.EchoStringResult = 'Mock response';
       response.put('response_x', respElement); 
   }
}
and WebSvcCallout is referenced also when setting the mock:
Test.setMock(WebServiceMock.class, new WebServiceMockImpl());
        
// Call the method that invokes a callout
String output = WebSvcCallout.callEchoString('Hello World!');
        
// Verify that a fake result is returned
System.assertEquals('Mock response', output);

 
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri
Sorry just get rid of docsample class and use your class instead of docsample
msaz87msaz87
When I get rid of the docsample class, I get the following errors:
  • WebSvcCallout: Invalid type: docSample.DocSamplePort
  • WebServiceMockImpl: Invalid type: docSample.EchoStringResponse_element
  • testUpdateContactAfterConvertedOrig: Dependent class is invalid and needs recompilation: WebServiceMockImpl: line 14, column 16: Invalid type: docSample.EchoStringResponse_element
And here are the classes:

WebSvcCallout
public class WebSvcCallout {
    public static String callEchoString(String input) {
        docSample.DocSamplePort sample = new docSample.DocSamplePort();
        sample.endpoint_x = 'http://api.salesforce.com/foo/bar';
        
        // This invokes the EchoString method in the generated class
        String echo = sample.EchoString(input);
        
        return echo;
    }   
}
WebServiceMockImpl
@isTest
global class WebServiceMockImpl implements WebServiceMock {
   global void doInvoke(
           Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType) {
       docSample.EchoStringResponse_element respElement = 
           new docSample.EchoStringResponse_element();
       respElement.EchoStringResult = 'Mock response';
       response.put('response_x', respElement); 
   }
}
testUpdateContactAfterConvertedOrig
@isTest
    private class testUpdateContactAfterConvertedOrig {
    
        static testmethod void myUnitTest() {
                Test.startTest();
                
        // This causes a fake response to be generated
        Test.setMock(WebServiceMock.class, new WebServiceMockImpl());
        
        // Call the method that invokes a callout
        String output = WebSvcCallout.callEchoString('Hello World!');
        
        // Verify that a fake result is returned
        System.assertEquals('Mock response', output);                 
                
                // Create new test lead
                Lead myLead = new Lead(LastName = 'Fry', Company='Fry And Sons', LeadSource = 'Advertising', Lead_Source_Detail__c = 'PPC');
                insert myLead;
                
                // Convert test lead
                Database.LeadConvert lc = new Database.LeadConvert();
                lc.setLeadId(myLead.id);
                
                // Check conversion
                LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
                lc.setConvertedStatus(convertStatus.MasterLabel);
				lc.setDoNotCreateOpportunity(True);
                
                // Declare successful
                //Test.startTest(); 
                Database.LeadConvertResult lcr = Database.convertLead(lc);
                Test.stopTest();
                System.assert(lcr.isSuccess());
    
        }
    }



 
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri

Getting rid of doc sample means we need to remove refereces in other classes as well just take out docsample class and put your class.

 

msaz87msaz87
But docSample has other classes within it being used, like DocSamplePort and EchoStringResponse_element. Wouldn't this not work?

If I updated the two classes they would look like this:

WebSvcCallout
public class WebSvcCallout {
    public static String callEchoString(String input) {
        updateContactAfterConvertedFuture.DocSamplePort sample = new updateContactAfterConvertedFuture.DocSamplePort();
        sample.endpoint_x = 'http://api.salesforce.com/foo/bar';
        
        // This invokes the EchoString method in the generated class
        String echo = sample.EchoString(input);
        
        return echo;
    }   
}
WebServiceMockImpl
@isTest
global class WebServiceMockImpl implements WebServiceMock {
   global void doInvoke(
           Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType) {
       updateContactAfterConvertedFuture.EchoStringResponse_element respElement = 
           new updateContactAfterConvertedFuture.EchoStringResponse_element();
       respElement.EchoStringResult = 'Mock response';
       response.put('response_x', respElement); 
   }
}

 
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri

I don't know in line 3 why oyu kept DocSamplePort() ?? you have to put your future method there.

are you new to coding ?

msaz87msaz87
Yes, I have very little experience with Java or Apex.

So is this correct?

WebSvcCallout
public class WebSvcCallout {
    public static String callEchoString(String input) {
        updateContactAfterConverted.updateContactAfterConvertedFuture sample = new updateContactAfterConverted.updateContactAfterConvertedFuture();
        sample.endpoint_x = 'http://api.salesforce.com/foo/bar';
        
        // This invokes the EchoString method in the generated class
        String echo = sample.EchoString(input);
        
        return echo;
    }   
}
WebServiceMockImpl
@isTest
global class WebServiceMockImpl implements WebServiceMock {
   global void doInvoke(
           Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType) {
       updateContactAfterConverted.EchoStringResponse_element respElement = 
           new updateContactAfterConverted.EchoStringResponse_element();
       respElement.EchoStringResult = 'Mock response';
       response.put('response_x', respElement); 
   }
}

 
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri

remove 13 to 17 in WebServiceMockImpl

 

 

msaz87msaz87
How would I modify line 3 in WebSvcCallout?
public class WebSvcCallout {
    public static String callEchoString(String input) {
        docSample.DocSamplePort sample = new docSample.DocSamplePort();
        sample.endpoint_x = 'http://api.salesforce.com/foo/bar';
        
        // This invokes the EchoString method in the generated class
        String echo = sample.EchoString(input);
        
        return echo;
    }   
}

 
Suraj Tripathi 47Suraj Tripathi 47
Hi Siva,

Greetings!

The method which is testmethod, does not allow web callout.
So it means test classes are not allowed to web callout.
So its solution is to create a fake response.
To creating a fake response, use HttpCalloutMock interface.

If you find your Solution then mark this as the best answer. 

Thank you!

Regards,
Suraj Tripathi